[
  {
    "path": ".gitignore",
    "content": ".vagrant/\n.idea/\n.venv/\n.archives/\nwriteup/\ndocs/scenarios/\ndocs/notes.md\ntemp/\nansible/.venv/\nansible/collections/\nansible/test.yml\n*VBoxHeadless*.log\n.terraform/\n.terraform.lock.hcl\n*.tfstate*\ntfplan\n*.pem\nad/PURPLE\nad/REDLAB\nad/EDRLAB\nad/DEMO\nad/FEDGOAD\nansible/roles/edr\nansible/edr.yml\nansible/private_data_dir/artifacts/\n.vscode\nad/MINILAB\nad/*/providers/*/ssh_keys/*id_rsa*\nad/*/providers/*/ssh_keys/*.pub\nad/*/providers/*/extensions/*.rb\n__pycache__/\n*.pyc\nworkspace/*\ntodo.md\nnext_extensions/\n/extensions/exchange/ansible/iso/resources/iso/*.ISO\ndocs/site/\ndocs/olddocs/\ndocs/mkdocs/site/\nscripts/archives/\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM ubuntu:22.04\n\nRUN apt-get update \\\n    && apt-get install -y python3-pip\n\nRUN pip install --upgrade pip\nRUN pip install ansible-core==2.12.6\nRUN pip install pywinrm\n\nRUN apt-get update -y && \\\n    DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \\\n    sshpass lftp rsync openssh-client\n\nCOPY ./ansible/requirements.yml .\n\nRUN ansible-galaxy install -r requirements.yml\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n  <h1><img alt=\"GOAD (Game Of Active Directory)\" src=\"./docs/mkdocs/docs/img/logo_GOAD3.png\"></h1>\n  <br>\n</div>\n\n**GOAD (v3)**\n\n:bookmark: Documentation : [https://orange-cyberdefense.github.io/GOAD/](https://orange-cyberdefense.github.io/GOAD/)\n\n## Description\nGOAD is a pentest active directory LAB project.\nThe purpose of this lab is to give pentesters a vulnerable Active directory environment ready to use to practice usual attack techniques.\n\n> [!CAUTION]\n> This lab is extremely vulnerable, do not reuse recipe to build your environment and do not deploy this environment on internet without isolation (this is a recommendation, use it as your own risk).<br>\n> This repository was build for pentest practice.\n\n![goad_screenshot](./docs/img/goad_screenshot.png)\n\n## Licenses\nThis lab use free Windows VM only (180 days). After that delay enter a license on each server or rebuild all the lab (may be it's time for an update ;))\n\n## Available labs\n\n- GOAD Lab family and extensions overview\n<div align=\"center\">\n<img alt=\"GOAD\" width=\"800\" src=\"./docs/img/diagram-GOADv3-full.png\">\n</div>\n\n- [GOAD](https://orange-cyberdefense.github.io/GOAD/labs/GOAD/) : 5 vms, 2 forests, 3 domains (full goad lab)\n<div align=\"center\">\n<img alt=\"GOAD\" width=\"800\" src=\"./docs/img/GOAD_schema.png\">\n</div>\n\n- [GOAD-Light](https://orange-cyberdefense.github.io/GOAD/labs/GOAD-Light/) : 3 vms, 1 forest, 2 domains (smaller goad lab for those with a smaller pc)\n<div align=\"center\">\n<img alt=\"GOAD Light\" width=\"600\" src=\"./docs/img/GOAD-Light_schema.png\">\n</div>\n\n- [MINILAB](https://orange-cyberdefense.github.io/GOAD/labs/MINILAB/): 2 vms, 1 forest, 1 domain (basic lab with one DC (windows server 2019) and one Workstation (windows 10))\n\n- [SCCM](https://orange-cyberdefense.github.io/GOAD/labs/SCCM/) : 4 vms, 1 forest, 1 domain, with microsoft configuration manager installed\n<div align=\"center\">\n<img alt=\"SCCM\" width=\"600\" src=\"./docs/img/SCCMLAB_overview.png\">\n</div>\n\n- [NHA](https://orange-cyberdefense.github.io/GOAD/labs/NHA/) : A challenge with 5 vms and 2 domains. no schema provided, you will have to find out how break it.\n<div align=\"center\">\n<img alt=\"SCCM\" width=\"600\" src=\"./docs/img/logo_NHA.jpeg\">\n</div>\n\n- [DRACARYS](https://orange-cyberdefense.github.io/GOAD/labs/DRACARYS/) : A challenge with 3 vms and 1 domains. no schema provided, you will have to find out how break it.\n<div align=\"center\">\n<img alt=\"SCCM\" width=\"600\" src=\"./docs/img/dracarys_logo.png\">\n</div>"
  },
  {
    "path": "ad/DRACARYS/README.md",
    "content": "# DRACARYS\n\n![DRACARYS](../../docs/img/dracarys_logo.png)\n\n- DRACARYS is written as a training challenge where GOAD was written as a lab with a maximum of vulns.\n- You should find your way in to get domain admin on the domain dracarys.lab\n- Using vagrant user is prohibited of course ^^\n- Starting point is on lx01 : `<ip_range>.12`\n- Obviously do not cheat by looking at the passwords and flags in the recipe files, the lab must start without user to full compromise. \n- If you use goad previously your ansible requirements may not be up to date. Be sure to do this before the install:\n\n```bash\nsource ~/.goad/.venv/bin/activate\ncd ~/GOAD/ansible\n\n# if you python is >=3.11\nansible-galaxy install -r requirements_311.yml \n# if you got a python <3.10\nansible-galaxy install -r requirements.yml \n```\n\n- Install :\n\n```bash\n./goad.sh -t install -l DRACARYS -p virtualbox\n```\n\nor\n\n```bash\n./goad.sh\n> set_lab DRACARYS\n> set_provider <your_provider>\n> set_iprange 192.168.56  # select the one you want and you can skip this with ludus\n> install\n```\n\n- Once install finish disable vagrant user to avoid using it :\n\n```bash\n./goad.sh\n> load <instance_id>\n> disable_vagrant\n```\n\n- Now do a reboot of all the machine to avoid unintended secrets stored : \n\n```bash\n> stop\n> start\n```\n\nAnd you are ready to play ! :)\n\n- If you need to re-enable vagrant\n\n```bash\n> load <instance_id>\n> enable_vagrant\n```\n\n- If you want to create a write up of the chall, no problem, have fun. Please ping me on X (@M4yFly) or Discord, i will be happy to read it :)\n\n!!! tip\n    Be sure to get your arsenal up to date\n"
  },
  {
    "path": "ad/DRACARYS/data/config.json",
    "content": "{\n\"lab\" : {\n    \"hosts\" : {\n        \"dc01\" : {\n            \"hostname\" : \"balerion\",\n            \"type\" : \"dc\",\n            \"local_admin_password\": \"8dCsfT-DJjgS3xdcp\",\n            \"domain\" : \"dracarys.lab\",\n            \"path\" : \"DC=dracarys,DC=lab\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"dracarys\\\\Drogon\"\n                ]\n            },\n            \"scripts\" : [\"set_spn.ps1\",\"wsman_kerb.ps1\"],\n            \"security\": [\"directory\", \"files\", \"ldaps\"],\n            \"security_vars\": {\n                \"directory\": {\n                    \"setup\": \"c:\\\\setup\"\n                },\n                \"files\" : {\n                    \"certificate\" : {\n                        \"src\" : \"dc01/ldaps.pfx\",\n                        \"dest\" : \"c:\\\\setup\\\\ldaps.pfx\"\n                    }\n                },\n                \"ldaps\": {\n                    \"certificate\" : {\n                        \"pfx\" : \"c:\\\\setup\\\\ldaps.pfx\",\n                        \"cert_password\" : \"MyStr@ngeCertP@ssword123\"\n                    }\n                }\n            },\n            \"vulns\" : [\"files\", \"enable_credssp_client\", \"schedule\"],\n            \"vulns_vars\" : {\n                \"files\" : {\n                    \"bot_keepass\" : {\n                        \"src\" : \"dc01/keepass_bot.ps1\",\n                        \"dest\" : \"c:\\\\keepass_bot.ps1\"\n                    }\n                },\n                \"schedule\": {\n                    \"bot\": {\n                        \"name\": \"keepass_bot\",\n                        \"cmd\" : \"powershell c:\\\\keepass_bot.ps1\",\n                        \"interval\" : \"PT1M\",\n                        \"multiple_instances\" : \"3\"\n                    }\n                }\n            }\n        },\n        \"srv01\" : {\n            \"hostname\" : \"vhagar\",\n            \"type\" : \"server\",\n            \"local_admin_password\": \"NgtkgtIAs75cKV+Pu\",\n            \"domain\" : \"dracarys.lab\",\n            \"path\" : \"DC=dracarys,DC=lab\",\n            \"use_laps\": false,\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"dracarys\\\\Rhaegal\"\n                ],\n                \"Remote Desktop Users\" : [\n                     \"dracarys\\\\Rhaegal\"\n                ]\n            },\n            \"scripts\" : [],\n            \"vulns\" : [\"files\", \"enable_credssp_server\", \"schedule\"],\n            \"vulns_vars\" : {\n                \"files\" : {\n                    \"vault\" : {\n                        \"src\" : \"srv01/vault.kdbx\",\n                        \"dest\" : \"c:\\\\vault.kdbx\"\n                    },\n                    \"bot_ssh\" : {\n                        \"src\" : \"srv01/bot_ssh.ps1\",\n                        \"dest\" : \"c:\\\\bot_ssh.ps1\"\n                    }\n                },\n                \"schedule\": {\n                    \"bot\": {\n                        \"name\": \"bot_ssh\",\n                        \"cmd\" : \"powershell c:\\\\bot_ssh.ps1\",\n                        \"interval\" : \"PT1M\"\n                    }\n                }\n            }\n        },\n        \"lx01\" : {\n              \"hostname\" : \"syrax\", \n              \"type\" : \"server\",\n              \"os\": \"linux\",\n              \"local_admin_password\": \"HGLXaxQSP@ssw_rd$\",\n              \"domain\" : \"dracarys.lab\", \n              \"path\" : \"DC=dracarys,DC=lab\",\n              \"local_groups\" : {\n                  \"sudoers\" : [\"LinuxAdmins\"],\n                  \"ssh\" : [\"LinuxAdmins\", \"LinuxUsers\"]\n              },\n              \"security\": [],\n              \"security_vars\": {},\n              \"scripts\" : []\n        }\n    },\n    \"domains\" : {\n        \"dracarys.lab\" : {\n            \"dc\": \"dc01\",\n            \"domain_password\" : \"8dCsfT-DJjgS3xdcp\",\n            \"netbios_name\": \"DRACARYS\",\n            \"organisation_units\" : {\n            },\n            \"groups\" : {\n                \"universal\" : {},\n                \"global\" : {\n                    \"LinuxAdmins\" : {\n                        \"managed_by\" : \"drogon\",\n                        \"path\" : \"CN=Users,DC=dracarys,DC=lab\"\n                    },\n                    \"LinuxUsers\" : {\n                        \"managed_by\" : \"drogon\",\n                        \"path\" : \"CN=Users,DC=dracarys,DC=lab\"\n                    }\n                },\n                \"domainlocal\" : {}\n            },\n            \"multi_domain_groups_member\" : {},\n            \"acls\" : {\n                \"WriteSPN_viserion_vhagar\": {\"for\": \"viserion\", \"to\": \"vhagar$\", \"right\": \"Ext-Write-SPN\", \"inheritance\": \"None\"},\n            },\n            \"users\" : {\n                \"drogon\" : {\n                    \"firstname\"   : \"drogon\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"sUIjHxs1i0yxZsGBreh0\", \n                    \"city\"        : \"-\",\n                    \"description\" : \"Domain admin\",\n                    \"groups\"      : [\"LinuxAdmins\", \"Domain Admins\"],\n                    \"path\"        : \"CN=Users,DC=dracarys,DC=lab\"\n                },\n                \"rhaegal\" : {\n                    \"firstname\"   : \"rhaegal\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"ufsmcvDaFz1uEqzAtaiL\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"Rhaegal\",\n                    \"groups\"      : [\"LinuxAdmins\"],\n                    \"path\"        : \"CN=Users,DC=dracarys,DC=lab\"\n                },\n                \"viserion\" : {\n                    \"firstname\"   : \"viserion\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"aLHtz1WvIVmeV4Zh4CDE\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"viserion\",\n                    \"groups\"      : [\"LinuxUsers\"],\n                    \"path\"        : \"CN=Users,DC=dracarys,DC=lab\"\n                },\n                \"sunfyre\" : {\n                    \"firstname\"   : \"sunfyre\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"BSno5DP4tjJ4jIu8is3B\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"glpi service account\",\n                    \"groups\"      : [\"LinuxUsers\"],\n                    \"path\"        : \"CN=Users,DC=dracarys,DC=lab\"\n                }\n            }\n        }\n    }\n}}"
  },
  {
    "path": "ad/DRACARYS/data/inventory",
    "content": "; GLOBAL CONFIG\n[all:vars]\n; domain_name : folder inside ad/\ndomain_name=DRACARYS\n\n; administrator user\nadmin_user=administrator\n\n; global settings inventory default value\nkeyboard_layouts=[\"en-US\", \"da-DK\", \"fr-FR\"]\n\n; modify this to add a default route\nadd_route=no\nroute_gateway=192.168.56.1\nroute_network=10.0.0.0/8\n\n; modify this to enable http proxy\nenable_http_proxy=no\nad_http_proxy=http://x.x.x.x:xxxx\nad_https_proxy=http://x.x.x.x:xxxx\n\n;force_dns_server\nforce_dns_server=no\ndns_server=1.1.1.1\n\n;dns server forwarder\ndns_server_forwarder=1.1.1.1\n\n; winrm connection (windows)\nansible_user=vagrant\nansible_password=vagrant\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n# ansible_winrm_transport=basic\n# ansible_port=5985\n\n; proxy settings (the lab need internet for some install, if you are behind a proxy you should set the proxy here)\nenable_http_proxy=no\nad_http_proxy=http://x.x.x.x:xxxx\nad_https_proxy=http://x.x.x.x:xxxx\n\n; LAB SCENARIO CONFIGURATION -----------------------------\n\n; computers inside domain (mandatory)\n; usage : build.yml, ad-relations.yml, ad-servers.yml, vulnerabilities.yml\n[domain]\ndc01\nsrv01\n\n[linux_domain]\nlx01\n\n; domain controler (mandatory)\n; usage : ad-acl.yml, ad-data.yml, ad-relations.yml, laps.yml\n[dc]\ndc01\n\n; domain server to enroll (mandatory if you want servers)\n; usage : ad-data.yml, ad-servers.yml, laps.yml\n[server]\nsrv01\n\n; workstation to enroll (mandatory if you want workstation)\n; usage : ad-servers.yml, laps.yml\n[workstation]\n\n; parent domain controler (mandatory)\n; usage : ad-servers.yml\n[parent_dc]\ndc01\n\n; child domain controler (need a fqdn child_name.parent_name)\n; usage : ad-servers.yml\n[child_dc]\n\n; allow computer update\n; usage : update.yml\n[update]\ndc01\n\n; disable update\n; usage : update.yml\n[no_update]\nsrv01\n\n; allow defender\n; usage : security.yml\n[defender_on]\ndc01\nsrv01\n\n; disable defender\n; usage : security.yml\n[defender_off]\n\n[glpi]\nlx01\n\n[klink]\nsrv01\n\n[keepass]\nsrv01\n\n;stay empty until override\n[extensions]"
  },
  {
    "path": "ad/DRACARYS/data/inventory_disable_vagrant",
    "content": "[default]\n; ------------------------------------------------\n; dracarys.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=drogon@dracarys.lab ansible_password=sUIjHxs1i0yxZsGBreh0\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01 ansible_user=drogon@dracarys.lab ansible_password=sUIjHxs1i0yxZsGBreh0\nlx01 ansible_host={{ip_range}}.12  dict_key=lx01 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no' ansible_user=drogon ansible_password=sUIjHxs1i0yxZsGBreh0\n\n[all:vars]\n; domain_name : folder inside ad/\ndomain_name=DRACARYS\n\n; winrm connection (windows)\nansible_winrm_transport=ntlm\nansible_user=notused\nansible_password=notused\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n\n; LAB SCENARIO CONFIGURATION -----------------------------\n[domain]\ndc01\nsrv01\n\n[linux_domain]\nlx01"
  },
  {
    "path": "ad/DRACARYS/files/dc01/cert.md",
    "content": "openssl genrsa -out ldaps.key 2048\nopenssl req -new -x509 -key ldaps.key -out ldaps.crt -days 3650 -subj \"/CN=balerion.dracarys.lab\" -addext \"subjectAltName = DNS:balerion.dracarys.lab,DNS:balerion\"\nopenssl pkcs12 -export -out ldaps.pfx -inkey ldaps.key -in ldaps.crt -passout pass:MyStr@ngeCertP@ssword123\n"
  },
  {
    "path": "ad/DRACARYS/files/dc01/keepass_bot.ps1",
    "content": "$pass = ConvertTo-SecureString 'ufsmcvDaFz1uEqzAtaiL' -AsPlainText -Force\n$creds = New-Object System.Management.Automation.PSCredential (\n    'dracarys.lab\\rhaegal',\n    $pass\n)\n\nInvoke-Command `\n    -ComputerName vhagar.dracarys.lab `\n    -Authentication Credssp `\n    -Credential $creds `\n    -ScriptBlock {\n        $kpPath = '\"C:\\Program Files\\KeePass Password Safe 2\\KeePass.exe\"'\n        $dbPath = 'C:\\vault.kdbx'\n        $masterPassword = 'lj-endlmkfQSLDKPDFNZLEK'\n        $openTime = 30\n\n        Write-Host \"[*] Start KeePass via cmd pipe\"\n\n        cmd /c \"echo $masterPassword | $kpPath $dbPath -pw-stdin\"\n\n        Write-Host \"[+] KeePass started\"\n        Start-Sleep -Seconds $openTime\n\n        Write-Host \"[-] Closing KeePass\"\n        Get-Process KeePass -ErrorAction SilentlyContinue | Stop-Process -Force\n    }\n"
  },
  {
    "path": "ad/DRACARYS/files/dc01/ldaps.crt",
    "content": "-----BEGIN CERTIFICATE-----\nMIIDTTCCAjWgAwIBAgIUU2yqCIa/Vzxgktgu/1gcLG6OjMkwDQYJKoZIhvcNAQEL\nBQAwIDEeMBwGA1UEAwwVYmFsZXJpb24uZHJhY2FyeXMubGFiMB4XDTI1MTIwODA4\nNTk0OVoXDTM1MTIwNjA4NTk0OVowIDEeMBwGA1UEAwwVYmFsZXJpb24uZHJhY2Fy\neXMubGFiMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl+jBdQImgoxK\nd52vvYnmtgLqF7M5v6620aBAMOs316P1SBX8GVrdpWo2uC+pYF78TK5/MfP8QLs5\nQMM3Qb46Y8rtA6Gueg9fQcTJAI9rsLg+JCA3YjWlvSN3yEjdHuZ1vQO6Ttjb1S29\nORl3MBEiqW2JTkS2xiFwhRNFV900TSoHKF1ZCqp1jvqS73f8kjaGckJ3Xq2IU3WU\nFQvpWGlKWvJxKN2MDAhB48mtscDvi9kfkTbXDn5w8ChWtWeTdDi5fQaRezTNdOzu\ngfZoMZKrNVdvR4DhHYPrk8YXsVJf7LuVcOhRHykzCcMqEF7eH2AKpB9EitycJIEV\nLGA8dryqgQIDAQABo38wfTAdBgNVHQ4EFgQU/OzihMQWP+/mO+HcNdR8Dn7QWpYw\nHwYDVR0jBBgwFoAU/OzihMQWP+/mO+HcNdR8Dn7QWpYwDwYDVR0TAQH/BAUwAwEB\n/zAqBgNVHREEIzAhghViYWxlcmlvbi5kcmFjYXJ5cy5sYWKCCGJhbGVyaW9uMA0G\nCSqGSIb3DQEBCwUAA4IBAQAZhdFOXz/WMPFewlHnDIMuVdkJPIHjMHyUCIdX7CtV\nwiEw0u2U6If6hXgsMw7WbYFhQRDWvR+zKLfL4xODxYivtAhr/P4T0jGqznTk6y5T\nYU59K4NSGj7iJzkF0euRbPWJWdK9i+YG0TyGB4xanl6jOqjLZPt7UxL+IFM73Qxf\nMnhn8YxqXg2vTPdknoaqytu3oD4st3bdSH6+ssthBnExm6PpCCnp3a7hosO6I4JZ\nae5zg5Wy3jcXghOHA3h+MKgk4CTNLjQBNioVBY7gfoW4GzcjxkfiBufxlfvtH7pd\n/WUoRKKmKUfOEMATBvCFxoAm+8cW3HlSVCjgZWBwbT6X\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "ad/DRACARYS/files/dc01/ldaps.key",
    "content": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCX6MF1AiaCjEp3\nna+9iea2AuoXszm/rrbRoEAw6zfXo/VIFfwZWt2laja4L6lgXvxMrn8x8/xAuzlA\nwzdBvjpjyu0Doa56D19BxMkAj2uwuD4kIDdiNaW9I3fISN0e5nW9A7pO2NvVLb05\nGXcwESKpbYlORLbGIXCFE0VX3TRNKgcoXVkKqnWO+pLvd/ySNoZyQnderYhTdZQV\nC+lYaUpa8nEo3YwMCEHjya2xwO+L2R+RNtcOfnDwKFa1Z5N0OLl9BpF7NM107O6B\n9mgxkqs1V29HgOEdg+uTxhexUl/su5Vw6FEfKTMJwyoQXt4fYAqkH0SK3JwkgRUs\nYDx2vKqBAgMBAAECggEANgAerTqLeALpAeaDL4yTAAa/MpeaosI36QLfbsRfAIAf\nVHXEPTso6YF9XDJNMp3xcEzjmF1UQaqMarI6tVsrJIhhgtX50Rgf06Bhl5pkPNjx\n9iOhrH7HoRm3nfIQ8MgZ+IwXsamzU+/DgUXFMcgVm0b99V3F317JwfScxOQ0kG0g\n5uD9QDfxRRAJ0DbLYovFYG2Xg8+BAldb9S7gD3JTVLRDEmSixruSkK0hHQA2GNGP\nbxvEJpgS153Qv6NbHCwJAWEY3HWhPBBzd5ObC0DVDPs56AzFsTdbjaIKbCFYfyPY\nwRw+r66aIw3cx9143GZEXlgM29lvM3lfpx0f1eBvRQKBgQC7kivCqUQQjAse2QbR\nuMnZuuXS0gPgD4Dk+48rbsvE6g8FG84FQmoB9hiAi4jT5nEQKgHg2I+NQRnu4spz\nMpwBhhZC/12mtBW6kTRSzuoGdJhivZHarTuvH6+nnkw7uwzDnB7BrnhHhbosgpb7\nfhsVritbA3f+s6VCXIJOisJ4hwKBgQDPVAWcIAyMAn4QaGjuLYdxkBE1AukCGTTS\nIAQsRFUb9i8PA8zvIXTrJjACJlNTVfDuPk4qp68eO/GwQRHFqTXlmz/Lhvdn9m9p\nCWpmL4fLpLYjdTZ8iFXlvjW155PuPCmE0vD3qtQKlYo03LVtcxgX3VhHgQQ2RT0l\nx/UmEr3utwKBgHtB8JO4m0usW1poDz0dizcSxBenfnhsd60BSfGmmyzJChm3TcjS\n/cpQJ4XBK6bjlYSjthxE8wBFuX7rdVIB/dZagKKCIM59JJI2/QU1hz+6urCYFhJ3\nJ/NKhSlGsp3FqvuXyfZIai3FyLObFRAqrC2xCDiErQOolX5oQBDQyj5dAoGAWDL+\nT/SyYb2Ns503RlvICt+m8k5SobnnZpyIKezH6CVKz7BmNjSdcIvGUKPNPt6IqFGJ\nH0xGiy4lGz4TOWtKqmrpMMQx6+BCdQS0ZtRBiLiBY4QxsbiuEhZg8wmZPPgLEZ5L\nNJFPs1D6gpKB/BXCYiSfsYuJJy09Xh06hP/kHPECgYBMUh9ZD8UJTLXdWqn2sLxS\nU+ippoaBR1PaD6Id/31FpR+5wuv78Kzz4e8wejMlp0oPMpxLrp78q0F0RGbVsZOy\nE78Sr9qrQWHDyjWImtkzcWAPcbsrUeBCAmsjCov17yCwBsCuODIT8oImuGBjDRrB\nJGj0b+OHm2nmez8vAmb0jg==\n-----END PRIVATE KEY-----\n"
  },
  {
    "path": "ad/DRACARYS/files/srv01/bot_ssh.ps1",
    "content": "$User = \"viserion\"\n$SSHHost = \"syrax\"\n$Password = \"aLHtz1WvIVmeV4Zh4CDE\"\n\n& \"C:\\Program Files\\PuTTY\\klink.exe\" -auto_store_sshkey $SSHHost -l \"$User\" -pw $Password \"sleep 45\"\n"
  },
  {
    "path": "ad/DRACARYS/providers/aws/inventory",
    "content": "[default]\n; ------------------------------------------------\n; dracarys.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=8dCsfT-DJjgS3xdcp\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01 ansible_user=ansible ansible_password=NgtkgtIAs75cKV+Pu\nlx01 ansible_host={{ip_range}}.12  dict_key=lx01 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no' ansible_user=goadmin ansible_password=HGLXaxQSP@ssw_rd$\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/DRACARYS/providers/aws/linux.tf",
    "content": "\"lx01\" = {\n  name               = \"lx01\"\n  linux_sku          = \"24_04-lts-gen2\"\n  linux_version      = \"latest\"\n  ami                = \"ami-0bb8b77ad97138af1\"\n  private_ip_address = \"{{ip_range}}.12\"\n  password           = \"HGLXaxQSP@ssw_rd$\"\n  instance_type      = \"t3.medium\"\n}"
  },
  {
    "path": "ad/DRACARYS/providers/aws/windows.tf",
    "content": "# Standard_B2s : 2 CPU / 4GB\n# Standard_B2ms : 2CPU / 8GB\n# Standard_B4ms : 4 cpu / 16 GB\n\"dc01\" = {\n  name               = \"dc01\"\n  domain             = \"dracarys.lab\"\n  windows_sku        = \"2025-Datacenter\"\n  ami                = \"ami-0979a3709cb073ec3\"\n  instance_type      = \"t3.medium\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCsfT-DJjgS3xdcp\"\n}\n\"srv01\" = {\n  name               = \"srv01\"\n  domain             = \"dracarys.lab\"\n  windows_sku        = \"2025-Datacenter\"\n  ami                = \"ami-0979a3709cb073ec3\"\n  instance_type      = \"t3.medium\"\n  private_ip_address = \"{{ip_range}}.11\"\n  password           = \"NgtkgtIAs75cKV+Pu\"\n}"
  },
  {
    "path": "ad/DRACARYS/providers/azure/inventory",
    "content": "[default]\n; ------------------------------------------------\n; dracarys.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=8dCsfT-DJjgS3xdcp\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01 ansible_user=ansible ansible_password=NgtkgtIAs75cKV+Pu\nlx01 ansible_host={{ip_range}}.12  dict_key=lx01 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no' ansible_user=goadmin ansible_password=HGLXaxQSP@ssw_rd$\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/DRACARYS/providers/azure/linux.tf",
    "content": "\"lx01\" = {\n  name               = \"lx01\"\n  linux_offer        = \"ubuntu-24_04-lts\"\n  linux_sku          = \"server\"\n  linux_version      = \"latest\"\n  private_ip_address = \"{{ip_range}}.12\"\n  password           = \"HGLXaxQSP@ssw_rd$\"\n  size               = \"Standard_B2s\"\n}"
  },
  {
    "path": "ad/DRACARYS/providers/azure/windows.tf",
    "content": "# Standard_B2s : 2 CPU / 4GB\n# Standard_B2ms : 2CPU / 8GB\n# Standard_B4ms : 4 cpu / 16 GB\n\"dc01\" = {\n  name               = \"dc01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2025-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCsfT-DJjgS3xdcp\"\n  size               = \"Standard_B2s\"\n}\n\"srv01\" = {\n  name               = \"srv01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2025-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.11\"\n  password           = \"NgtkgtIAs75cKV+Pu\"\n  size               = \"Standard_B2s\"\n}"
  },
  {
    "path": "ad/DRACARYS/providers/ludus/config.yml",
    "content": "ludus:\n  - vm_name: \"{{ range_id }}-DC01\"\n    hostname: \"{{ range_id }}-DC01\"\n    template: win2025-server-x64-tpm-template\n    vlan: 10\n    ip_last_octet: 10\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-SRV01\"\n    hostname: \"{{ range_id }}-SRV01\"\n    template: win2025-server-x64-tpm-template\n    vlan: 10\n    ip_last_octet: 11\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-LX01\"\n    hostname: \"{{ range_id }}-LX01\"\n    template: ubuntu-24.04-x64-server-template\n    vlan: 10\n    ip_last_octet: 12\n    ram_gb: 4\n    cpus: 2\n    linux: true\n"
  },
  {
    "path": "ad/DRACARYS/providers/ludus/inventory",
    "content": "[default]\n; ------------------------------------------------\n; dracarys.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01\nlx01 ansible_host={{ip_range}}.12 dict_key=lx01 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'\n\n[all:vars]\nforce_dns_server=no\ndns_server={{ip_range}}.254\n\ndns_server_forwarder={{ip_range}}.254\n\nansible_user=localuser\nansible_password=password"
  },
  {
    "path": "ad/DRACARYS/providers/proxmox/inventory",
    "content": "[default]\n; ------------------------------------------------\n; dracarys.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01\nlx01 ansible_host={{ip_range}}.12  dict_key=lx01 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no'\n\n[all:vars]\nforce_dns_server=yes\ndns_server={{ip_range}}.1\n"
  },
  {
    "path": "ad/DRACARYS/providers/proxmox/linux.tf",
    "content": "\"lx01\" = {\n  name               = \"LX01\"\n  desc               = \"LX01 - DRACARYS\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"Ubuntu_2404_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.12/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n"
  },
  {
    "path": "ad/DRACARYS/providers/proxmox/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"DC01\"\n  desc               = \"DC01 - DRACARYS - windows server 2025 - {{ip_range}}.10\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"WinServer2025_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.10/24\"\n  gateway            = \"{{ip_range}}.1\"\n  os                 = \"win11\"\n}\n\"srv01\" = {\n  name               = \"SRV01\"\n  desc               = \"SRV01 - DRACARYS- windows server 2025 - {{ip_range}}.11\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"WinServer2025_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.11/24\"\n  gateway            = \"{{ip_range}}.1\"\n  os                 = \"win11\"\n}"
  },
  {
    "path": "ad/DRACARYS/providers/virtualbox/Vagrantfile",
    "content": "boxes = \n[\n  { :name => \"DRACARYS-DC01\", \n    :ip => \"{{ip_range}}.10\", \n    :box => \"GOAD/WindowsServer2025\", \n    :box_version => \"2026.02.09\", \n    :os => \"windows\", \n    :cpus => 2, \n    :mem => 3000\n  },\n  { :name => \"DRACARYS-SRV01\", \n    :ip => \"{{ip_range}}.11\", \n    :box => \"GOAD/WindowsServer2025\", \n    :box_version => \"2026.02.09\", \n    :os => \"windows\", \n    :cpus => 2, \n    :mem => 3000\n  },\n  { :name => \"DRACARYS-LX01\",\n    :ip => \"{{ip_range}}.12\",\n    :box => \"bento/ubuntu-24.04\",\n    :box_version => \"202510.26.0\",\n    :os => \"linux\",\n    :cpus => 2,\n    :mem => 3000,\n    :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n  }\n]"
  },
  {
    "path": "ad/DRACARYS/providers/virtualbox/inventory",
    "content": "[default]\n; ------------------------------------------------\n; dracarys.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01\nlx01 ansible_host={{ip_range}}.12  dict_key=lx01 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no'\n"
  },
  {
    "path": "ad/DRACARYS/providers/vmware/Vagrantfile",
    "content": "boxes = \n[\n  { :name => \"DRACARYS-DC01\", \n    :ip => \"{{ip_range}}.10\", \n    :box => \"GOAD/WindowsServer2025\", \n    :box_version => \"2026.02.09\", \n    :os => \"windows\", \n    :cpus => 2, \n    :mem => 3000\n  },\n  { :name => \"DRACARYS-SRV01\", \n    :ip => \"{{ip_range}}.11\", \n    :box => \"GOAD/WindowsServer2025\", \n    :box_version => \"2026.02.09\", \n    :os => \"windows\", \n    :cpus => 2, \n    :mem => 3000\n  },\n  { :name => \"DRACARYS-LX01\",\n    :ip => \"{{ip_range}}.12\",\n    :box => \"bento/ubuntu-24.04\",\n    :box_version => \"202510.26.0\",\n    :os => \"linux\",\n    :cpus => 2,\n    :mem => 3000,\n    :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n  }\n]"
  },
  {
    "path": "ad/DRACARYS/providers/vmware/inventory",
    "content": "[default]\n; ------------------------------------------------\n; dracarys.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01\nlx01 ansible_host={{ip_range}}.12  dict_key=lx01 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no'\n"
  },
  {
    "path": "ad/DRACARYS/scripts/set_spn.ps1",
    "content": "Set-ADComputer -Identity \"syrax$\" -Add @{'msDS-AllowedToDelegateTo'=@('HTTP/arrax.dracarys.lab','HTTP/arrax')}\n"
  },
  {
    "path": "ad/DRACARYS/scripts/wsman_kerb.ps1",
    "content": "Set-ADComputer -Identity \"vhagar$\" -ServicePrincipalNames @{Add='WSMAN/vhagar.dracarys.lab'}\nSet-ADComputer -Identity \"vhagar$\" -Add @{'msDS-AllowedToDelegateTo'=@('WSMAN/vhagar.dracarys.lab')}\n"
  },
  {
    "path": "ad/GOAD/README.md",
    "content": "# GOAD\n\n- LAB Content \n\n![GOAD overview](../../docs/img/GOAD_schema.png)\n\n## Servers\nThis lab is actually composed of five virtual machines:\n- **kingslanding** : DC01  running on Windows Server 2019 (with windefender enabled by default)\n- **winterfell**   : DC02  running on Windows Server 2019 (with windefender enabled by default)\n- **castelblack**  : SRV02 running on Windows Server 2019 (with windefender **disabled** by default)\n- **meereen**      : DC03  running on Windows Server 2016 (with windefender enabled by default)\n- **braavos**      : SRV03 running on Windows Server 2016 (with windefender enabled by default)\n\n## domain : north.sevenkingdoms.local\n- **winterfell**     : DC01\n- **castelblack**    : SRV02 : MSSQL / IIS\n\n## domain : sevenkingdoms.local\n- **kingslanding**   : DC02\n- **castelrock**     : SRV01 (disabled due to resources reasons)\n\n## domain : essos.local\n- **braavos**        : DC03\n- **meeren**         : SRV03 : MSSQL / ADCS\n\nThe lab setup is automated using vagrant and ansible automation tools.\nYou can change the vm version in the Vagrantfile according to Stefan Scherer vagrant repository : https://app.vagrantup.com/StefanScherer\n\n\n## Users/Groups and associated vulnerabilites/scenarios\n\n- You can find a lot of the available scenarios on [https://mayfly277.github.io/categories/ad/](https://mayfly277.github.io/categories/ad/)\n\n- Graph of some scenarios is available here :\n![diagram-GOAD_compromission_Path_dark](./../../docs/img/diagram-GOAD_compromission_Path_dark.png)\n\nNORTH.SEVENKINGDOMS.LOCAL\n- STARKS:              RDP on WINTERFELL AND CASTELBLACK\n  - arya.stark:        Execute as user on mssql, pass on all share\n  - eddard.stark:      DOMAIN ADMIN NORTH/ (bot 5min) LLMRN request to do NTLM relay with responder\n  - catelyn.stark:     \n  - robb.stark:        bot (3min) RESPONDER LLMR / lsass present user\n  - sansa.stark:       keywalking password / unconstrained delegation\n  - brandon.stark:     ASREP_ROASTING\n  - rickon.stark:      pass spray WinterYYYY\n  - jon.snow:          mssql admin / KERBEROASTING / mssql trusted link\n  - hodor:             PASSWORD SPRAY (user=password)\n- NIGHT WATCH:         RDP on CASTELBLACK\n  - samwell.tarly:     Password in ldap description / mssql execute as login\n                       GPO abuse (Edit Settings on \"STARKWALLPAPER\" GPO)\n  - jon.snow:          (see starks)\n  - jeor.mormont:      (see mormont)\n- MORMONT:             RDP on CASTELBLACK\n  - jeor.mormont:      Admin castelblack, pass in sysvol script\n- AcrossTheSea :       cross forest group\n\nSEVENKINGDOMS.LOCAL\n- LANISTERS\n  - tywin.lannister:   ACE forcechangepassword on jaime.lanister, password on sysvol cyphered\n  - jaime.lannister:   ACE genericwrite-on-user joffrey.baratheon\n  - tyron.lannister:   ACE self membership on small council\n  - cersei.lannister:  DOMAIN ADMIN SEVENKINGDOMS\n- BARATHEON:           RDP on KINGSLANDING\n  - robert.baratheon:  DOMAIN ADMIN SEVENKINGDOMS, protected user\n  - joffrey.baratheon: ACE Write DACL on tyron.lannister\n  - renly.baratheon:   WriteDACL on container, sensitive user\n  - stannis.baratheon: ACE genericall-on-computer kingslanding \n- SMALL COUNCIL :      ACE add Member to group dragon stone / RDP on KINGSLANDING\n  - petyer.baelish:    \n  - lord.varys:        ACE genericall-on-group Domain Admins and sdholder\n  - maester.pycelle:   \n- DRAGONSTONE :        ACE Write Owner on group KINGSGUARD\n- KINGSGUARD :         ACE generic all on user stannis.baratheon\n- AccorsTheNarrowSea:       cross forest group\n\nESSOS.LOCAL\n- TARGERYEN\n  - missande :          ASREP roasting, generic all on khal\n  - daenerys.targaryen: DOMAIN ADMIN ESSOS\n  - viserys.targaryen:  ACE write property on jorah.mormont\n  - jorah.mormont:      mssql execute as login / mssql trusted link / Read LAPS Password\n- DOTHRAKI\n  - khal.drogo:         mssql admin / GenericAll on viserys (shadow credentials) / GenericAll on ECS4\n- DragonsFriends:       cross forest group\n- Spys:                 cross forest group / Read LAPS password  / ACL generic all jorah.mormont\n\n## Computers Users and group permissions\n\n- SEVENKINGDOMS\n  - DC01 : kingslanding.sevenkingdoms.local (Windows Server 2019) (SEVENKINGDOMS DC)\n    - Admins : robert.baratheon (U), cersei.lannister (U)\n    - RDP: Small Council (G)\n\n- NORTH\n  - DC02 : winterfell.north.sevenkingdoms.local (Windows Server 2019) (NORTH DC)\n    - Admins : eddard.stark (U), catelyn.stark (U), robb.stark (U)\n    - RDP: Stark(G)\n\n  - SRV02 : castelblack.essos.local (Windows Server 2019) (IIS, MSSQL, SMB share)\n    - Admins: jeor.mormont (U)\n    - RDP: Night Watch (G), Mormont (G), Stark (G)\n    - IIS : allow asp upload, run as NT Authority/network\n    - MSSQL:\n      - admin : jon.snow\n      - impersonate : \n        - execute as login : samwel.tarlly -> sa\n        - execute as user : arya.stark -> dbo\n      - link :\n        - to braavos : jon.snow -> sa\n\n- ESSOS\n  - DC03  : meereen.essos.local (Windows Server 2016) (ESSOS DC)\n    - Admins: daenerys.targaryen (U)\n    - RDP: Targaryen (G)\n\n  - SRV03 : braavos.essos.local (Windows Server 2016) (MSSQL, SMB share)\n    - Admins: khal.drogo (U)\n    - RDP: Dothraki (G)\n    - MSSQL :\n      - admin : khal.drogo\n      - impersonate :\n        - execute as login : jorah.mormont -> sa\n      - link:\n        - to castelblack: jorah.mormont -> sa\n\n## Blueteam / ELK\n\n- **elk** a kibana is configured on http://192.168.56.50:5601 to follow the lab events\n- infos : log encyclopedia : https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/\n- the elk is not installed by default due to resources reasons. \n\n- prerequistes: \n- you need `sshpass` for the elk installation\n```bash\nsudo apt install sshpass\n```\n- Chocolatey is needed to use elk. To install it run:\n```bash\nansible-galaxy collection install chocolatey.chocolatey \n```\n\n- To install and start the elk play the following commands :\n```bash\n./goad.sh -t install -l GOAD -p virtualbox -m local -r elk.yml -e elk\n#or\n./goad.sh -t install -l GOAD -p vmware -m local -r elk.yml -e elk\n```\n\n * -e : to add the elk in vagrantfile for the vagrant up\n * -r : to run only the elk.yml ansible script\n\nIf you want to only launch the elk.yml file without providing (vm creation), because your elk vm is already up do :\n```bash\n./goad.sh -t install -l GOAD -p virtualbox -m local -a -r elk.yml -e elk\n#or\n./goad.sh -t install -l GOAD -p vmware -m local -a -r elk.yml -e elk\n```\n\nIf you want to do that by hand:\n  1. run: `GOAD_VAGRANT_OPTIONS=elk vagrant up`\n\n  2. launch the elk provisionning with the command :\n  ```\n  cd ansible\n  ansible-playbook -i ../ad/GOAD/data/inventory -i ../ad/GOAD/providers/<your_provider>/inventory elk.yml\n  ```\n\n### V2 breaking changes\n- If you previously install the v1 do not try to update as a lot of things have changed. Just drop your old lab and build the new one (you will not regret it)\n- Chocolatey is no more used and basic tools like git or notepad++ are no more installed by default (as chocolatey regularly crash the install due to hitting rate on multiples builds)\n- ELK is no more installed by default to save resources but you still can install it separately (see the blueteam/elk part)\n- Dragonstone vm as disappear and there is no more DC replication in the lab to save resources\n- Wintefell is now a domain controller for the subdomain north of the sevenkingdoms.local domain\n\n"
  },
  {
    "path": "ad/GOAD/data/config.json",
    "content": "{\n\"lab\" : {\n    \"hosts\" : {\n        \"dc01\" : {\n            \"hostname\" : \"kingslanding\",\n            \"type\" : \"dc\",\n            \"local_admin_password\": \"8dCT-DJjgScp\",\n            \"domain\" : \"sevenkingdoms.local\",\n            \"path\" : \"DC=sevenkingdoms,DC=local\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"sevenkingdoms\\\\robert.baratheon\",\n                    \"sevenkingdoms\\\\cersei.lannister\",\n                    \"sevenkingdoms\\\\DragonRider\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"sevenkingdoms\\\\Small Council\",\n                    \"sevenkingdoms\\\\Baratheon\"\n                ]\n            },\n            \"scripts\" : [\"sidhistory.ps1\"],\n            \"vulns\" : [\"disable_firewall\", \"adcs_esc10_case1\", \"adcs_esc10_case2\"],\n            \"security\": [\"account_is_sensitive\"],\n            \"security_vars\": {\n                \"account_is_sensitive\" : { \"renly\": {\"account\" : \"renly.baratheon\"} }\n            }\n        },\n        \"dc02\" : {\n            \"hostname\" : \"winterfell\",\n            \"type\" : \"dc\",\n            \"local_admin_password\": \"NgtI75cKV+Pu\",\n            \"domain\" : \"north.sevenkingdoms.local\",\n            \"path\" : \"DC=north,DC=sevenkingdoms,DC=local\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"north\\\\eddard.stark\",\n                    \"north\\\\catelyn.stark\",\n                    \"north\\\\robb.stark\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"north\\\\Stark\"\n                ]\n            },\n            \"scripts\" : [\n                \"asrep_roasting.ps1\",\n                \"constrained_delegation_use_any.ps1\",\n                \"constrained_delegation_kerb_only.ps1\",\n                \"ntlm_relay.ps1\",\n                \"responder.ps1\",\n                \"gpo_abuse.ps1\",\n                \"rdp_scheduler.ps1\"\n            ],\n            \"vulns\" : [\"disable_firewall\",\"directory\", \"credentials\", \"autologon\", \"files\", \"enable_llmnr\", \"enable_nbt-ns\", \"shares\"],\n            \"vulns_vars\" : {\n                \"directory\": {\n                    \"setup\": \"c:\\\\setup\"\n                },\n                \"credentials\" : {\n                    \"TERMSRV/castelblack\": {\n                        \"username\" : \"north\\\\robb.stark\",\n                        \"secret\"   : \"sexywolfy\",\n                        \"runas\"    : \"north\\\\robb.stark\",\n                        \"runas_password\" : \"sexywolfy\"\n                    }\n                },\n                \"autologon\" : {\n                    \"robb.stark\" : {\n                        \"username\" : \"north\\\\robb.stark\",\n                        \"password\" : \"sexywolfy\"\n                    }\n                },\n                \"files\" : {\n                    \"rdp\" : {\n                        \"src\" : \"dc02/bot_rdp.ps1\",\n                        \"dest\" : \"c:\\\\setup\\\\bot_rdp.ps1\"\n                    },\n                    \"sysvol_fake_script\": {\n                        \"src\" : \"dc02/sysvol_scripts/script.ps1\",\n                        \"dest\": \"C:\\\\Windows\\\\SYSVOL\\\\domain\\\\scripts\\\\script.ps1\"\n                    },\n                    \"sysvol_secret\": {\n                        \"src\" : \"dc02/sysvol_scripts/secret.ps1\",\n                        \"dest\": \"C:\\\\Windows\\\\SYSVOL\\\\domain\\\\scripts\\\\secret.ps1\"\n                    }\n                }\n            }\n        },\n        \"srv02\" : {\n            \"hostname\" : \"castelblack\",\n            \"type\" : \"server\",\n            \"local_admin_password\": \"NgtI75cKV+Pu\",\n            \"domain\" : \"north.sevenkingdoms.local\",\n            \"path\" : \"DC=north,DC=sevenkingdoms,DC=local\",\n            \"use_laps\": false,\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"north\\\\jeor.mormont\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"north\\\\Night Watch\",\n                    \"north\\\\Mormont\",\n                    \"north\\\\Stark\"\n                ]\n            },\n            \"scripts\" : [],\n            \"vulns\" : [\"directory\", \"disable_firewall\", \"openshares\", \"files\", \"permissions\"],\n            \"vulns_vars\" : {\n                \"directory\": {\n                    \"shares\": \"C:\\\\shares\",\n                    \"all\": \"C:\\\\shares\\\\all\"\n                },\n                \"files\" : {\n                    \"website\" : {\n                        \"src\" : \"srv02/wwwroot\",\n                        \"dest\" : \"C:\\\\inetpub\\\\\"\n                    },\n                    \"letter_in_shares\": {\n                        \"src\" : \"srv02/all/arya.txt\",\n                        \"dest\": \"C:\\\\shares\\\\all\\\\arya.txt\"\n                    }\n                },\n                \"permissions\" : {\n                    \"IIS_IUSRS_upload\": {\n                        \"path\" : \"C:\\\\inetpub\\\\wwwroot\\\\upload\",\n                        \"user\" : \"IIS_IUSRS\",\n                        \"rights\" : \"FullControl\"\n                    }\n                },\n                \"shares\" : {\n                    \"thewall\" : {\n                        \"path\"   : \"C:\\\\thewall\",\n                        \"list\"   : \"yes\",\n                        \"full\"   : \"NORTH\\\\Stark\",\n                        \"change\" : \"NORTH\\\\jon.snow,NORTH\\\\samwell.tarly\",\n                        \"read\"   : \"Users\"\n                    }\n                }\n            },\n            \"mssql\":{\n                \"sa_password\": \"Sup1_sa_P@ssw0rd!\",\n                \"svcaccount\" : \"sql_svc\",\n                \"sysadmins\" : [\n                    \"NORTH\\\\jon.snow\"\n                ],\n                \"executeaslogin\" : {\n                    \"NORTH\\\\samwell.tarly\" : \"sa\",\n                    \"NORTH\\\\brandon.stark\" :  \"NORTH\\\\jon.snow\"\n                },\n                \"executeasuser\" : {\n                    \"arya_master_dbo\": {\n                        \"user\": \"NORTH\\\\arya.stark\",\n                        \"db\"  : \"master\",\n                        \"impersonate\" : \"dbo\"\n                    },\n                    \"arya_dbms_dbo\": {\n                        \"user\": \"NORTH\\\\arya.stark\",\n                        \"db\"  : \"msdb\",\n                        \"impersonate\" : \"dbo\"\n                    }\n                },\n                \"linked_servers\": {\n                    \"BRAAVOS\" : {\n                        \"data_src\": \"braavos.essos.local\",\n                        \"users_mapping\": [\n                            {\"local_login\": \"NORTH\\\\jon.snow\",\"remote_login\": \"sa\", \"remote_password\": \"sa_P@ssw0rd!Ess0s\"}\n                        ]\n                    }\n                }\n            }\n        },\n        \"dc03\" : {\n            \"hostname\" : \"meereen\",\n            \"type\" : \"dc\",\n            \"local_admin_password\": \"Ufe-bVXSx9rk\",\n            \"domain\" : \"essos.local\",\n            \"path\" : \"DC=essos,DC=local\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"essos\\\\daenerys.targaryen\",\n                    \"essos\\\\greatmaster\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"essos\\\\Targaryen\"\n                ]\n            },\n            \"scripts\" : [\"asrep_roasting2.ps1\"],\n            \"vulns\" : [\"ntlmdowngrade\", \"disable_firewall\",  \"adcs_esc7\", \"adcs_esc13\", \"adcs_esc15\"],\n            \"vulns_vars\" : {\n                \"adcs_esc7\": {\n                    \"viserys\": {\n                        \"ca_manager\": \"essos\\\\viserys.targaryen\"\n                    }\n                },\n                \"adcs_esc13\": {\n                    \"esc13\" : {\n                        \"adcs_esc13_group\": \"greatmaster\",\n                        \"adcs_esc13_template\": \"ESC13\"\n                    }\n                }\n            }\n        },\n        \"srv03\" : {\n            \"hostname\" : \"braavos\",\n            \"type\" : \"server\",\n            \"local_admin_password\": \"978i2pF43UJ-\",\n            \"domain\" : \"essos.local\",\n            \"path\" : \"DC=essos,DC=local\",\n            \"use_laps\": true,\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"essos\\\\khal.drogo\"\n                ]\n            },\n            \"Remote Desktop Users\" : [\n                \"essos\\\\Dothraki\"\n            ],\n            \"scripts\" : [],\n            \"vulns\" : [\"openshares\",\"disable_firewall\", \"adcs_esc6\", \"adcs_esc11\"],\n            \"security\": [\"enable_run_as_ppl\"],\n            \"mssql\":{\n                \"sa_password\": \"sa_P@ssw0rd!Ess0s\",\n                \"svcaccount\" : \"sql_svc\",\n                \"sysadmins\" : [\n                    \"ESSOS\\\\khal.drogo\"\n                ],\n                \"executeaslogin\" : {\n                    \"ESSOS\\\\jorah.mormont\" : \"sa\"\n                },\n                \"executeasuser\" : {},\n                \"linked_servers\": {\n                    \"CASTELBLACK\" : {\n                        \"data_src\": \"castelblack.north.sevenkingdoms.local\",\n                        \"users_mapping\": [\n                            {\"local_login\": \"ESSOS\\\\khal.drogo\",\"remote_login\": \"sa\", \"remote_password\": \"Sup1_sa_P@ssw0rd!\"}\n                        ]\n                    }\n                }\n            }\n        }\n    },\n    \"domains\" : {\n        \"essos.local\" : {\n            \"dc\": \"dc03\",\n            \"domain_password\" : \"Ufe-bVXSx9rk\",\n            \"netbios_name\": \"ESSOS\",\n            \"ca_server\": \"Braavos\",\n            \"trust\" : \"sevenkingdoms.local\",\n            \"laps_path\": \"OU=Laps,DC=essos,DC=local\",\n            \"organisation_units\" : {\n            },\n            \"laps_readers\": [\n                \"jorah.mormont\",\n                \"Spys\"\n            ],\n            \"groups\" : {\n                \"universal\" : {\n                    \"greatmaster\" : {\n                        \"path\" : \"CN=Users,DC=essos,DC=local\"\n                    }\n                },\n                \"global\" : {\n                    \"Targaryen\" : {\n                        \"managed_by\" : \"viserys.targaryen\",\n                        \"path\" : \"CN=Users,DC=essos,DC=local\"\n                    },\n                    \"Dothraki\" : {\n                        \"managed_by\" : \"khal.drogo\",\n                        \"path\" : \"CN=Users,DC=essos,DC=local\"\n                    },\n                    \"Dragons\":{\n                        \"managed_by\" : \"Administrator\",\n                        \"path\" : \"CN=Users,DC=essos,DC=local\"\n                    },\n                    \"QueenProtector\":{\n                        \"managed_by\" : \"Administrator\",\n                        \"path\" : \"CN=Users,DC=essos,DC=local\",\n                        \"members\" : [\"ESSOS\\\\Dragons\"]\n                    },\n                    \"Domain Admins\":{\n                        \"managed_by\" : \"Administrator\",\n                        \"path\" : \"CN=Users,DC=essos,DC=local\",\n                        \"members\" : [\"ESSOS\\\\QueenProtector\"]\n                    }\n                },\n                \"domainlocal\" : {\n                    \"DragonsFriends\" : {\n                        \"managed_by\" : \"daenerys.targaryen\",\n                        \"path\" : \"CN=Users,DC=essos,DC=local\"\n                    },\n                    \"Spys\" : {\n                        \"path\" : \"CN=Users,DC=essos,DC=local\"\n                    }\n                }\n            },\n            \"multi_domain_groups_member\" : {\n                \"DragonsFriends\" : [\n                    \"sevenkingdoms.local\\\\tyron.lannister\",\n                    \"essos.local\\\\daenerys.targaryen\"\n                ],\n                \"Spys\" : [\n                    \"sevenkingdoms.local\\\\Small Council\"\n                ]\n            },\n            \"gmsa\" : {\n                \"gmsa_account\": {\n                    \"gMSA_Name\" : \"gmsaDragon\",\n                    \"gMSA_FQDN\" : \"gmsaDragon.essos.local\",\n                    \"gMSA_SPNs\" : [\"HTTP/braavos\", \"HTTP/braavos.essos.local\"],\n                    \"gMSA_HostNames\" : [\"braavos\"]\n                }\n            },\n            \"acls\" : {\n                \"GenericAll_khal_viserys\" : {\"for\": \"khal.drogo\", \"to\": \"viserys.targaryen\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_spy_jorah\" : {\"for\": \"Spys\", \"to\": \"jorah.mormont\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_khal_esc4\" : {\"for\": \"khal.drogo\", \"to\": \"CN=ESC4,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"WriteProperty_petyer_domadmin\" : {\"for\": \"viserys.targaryen\", \"to\": \"jorah.mormont\", \"right\": \"WriteProperty\", \"inheritance\": \"All\"},\n                \"GenericWrite_DragonsFriends_braavos\" : {\"for\": \"DragonsFriends\", \"to\": \"braavos$\", \"right\": \"GenericWrite\", \"inheritance\": \"None\"},\n                \"GenericAll_missandei_khal\" : {\"for\": \"missandei\", \"to\": \"khal.drogo\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_gmsaDragon_drogo\" : {\"for\": \"gmsaDragon$\", \"to\": \"drogon\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericWrite_missandei_viserys\" : {\"for\": \"missandei\", \"to\": \"viserys.targaryen\", \"right\": \"GenericWrite\", \"inheritance\": \"None\"}\n            },\n            \"users\" : {\n                \"daenerys.targaryen\" : {\n                    \"firstname\"   : \"daenerys\",\n                    \"surname\"     : \"targaryen\",\n                    \"password\"    : \"BurnThemAll!\", \n                    \"city\"        : \"-\",\n                    \"description\" : \"Darnerys Targaryen\",\n                    \"groups\"      : [\"Targaryen\", \"Domain Admins\"],\n                    \"path\"        : \"CN=Users,DC=essos,DC=local\"\n                },\n                \"viserys.targaryen\" : {\n                    \"firstname\"   : \"viserys\",\n                    \"surname\"     : \"targaryen\",\n                    \"password\"    : \"GoldCrown\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"Viserys Targaryen\",\n                    \"groups\"      : [\"Targaryen\"],\n                    \"path\"        : \"CN=Users,DC=essos,DC=local\"\n                },\n                \"khal.drogo\" : {\n                    \"firstname\"   : \"khal\",\n                    \"surname\"     : \"drogo\",\n                    \"password\"    : \"horse\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"Khal Drogo\",\n                    \"groups\"      : [\"Dothraki\"],\n                    \"path\"        : \"CN=Users,DC=essos,DC=local\"\n                },\n                \"jorah.mormont\" : {\n                    \"firstname\"   : \"jorah\",\n                    \"surname\"     : \"mormont\",\n                    \"password\"    : \"H0nnor!\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"Jorah Mormont\",\n                    \"groups\"      : [\"Targaryen\"],\n                    \"path\"        : \"CN=Users,DC=essos,DC=local\"\n                },\n                \"missandei\" : {\n                    \"firstname\"   : \"missandei\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"fr3edom\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"missandei\",\n                    \"groups\"      : [],\n                    \"path\"        : \"CN=Users,DC=essos,DC=local\"\n                },\n                \"drogon\" : {\n                    \"firstname\"   : \"drogon\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"Dracarys\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"drogon\",\n                    \"groups\"      : [\"Dragons\"],\n                    \"path\"        : \"CN=Users,DC=essos,DC=local\"\n                },\n                \"sql_svc\" : {\n                    \"firstname\"   : \"sql\",\n                    \"surname\"     : \"service\",\n                    \"password\"    : \"YouWillNotKerboroast1ngMeeeeee\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"sql service\",\n                    \"groups\"      : [],\n                    \"path\"        : \"CN=Users,DC=essos,DC=local\",\n                    \"spns\"        : [\"MSSQLSvc/braavos.essos.local:1433\",\"MSSQLSvc/braavos.essos.local\"]\n                }\n            }\n        },\n        \"north.sevenkingdoms.local\" : {\n            \"dc\": \"dc02\",\n            \"domain_password\" : \"NgtI75cKV+Pu\",\n            \"netbios_name\": \"NORTH\",\n            \"trust\" : \"\",\n            \"laps_path\": \"OU=Laps,DC=north,DC=sevenkingdoms,DC=local\",\n            \"organisation_units\" : {\n            },\n            \"groups\" : {\n                \"universal\" : {},\n                \"global\" : {\n                    \"Stark\" : {\n                        \"managed_by\" : \"eddard.stark\",\n                        \"path\" : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"Night Watch\" : {\n                        \"managed_by\" : \"jeor.mormont\",\n                        \"path\" : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"Mormont\" : {\n                        \"managed_by\" : \"jeor.mormont\",\n                        \"path\" : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                    }\n                },\n                \"domainlocal\" : {\n                    \"AcrossTheSea\" : {\n                        \"path\" : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                    }\n                }\n            },\n            \"multi_domain_groups_member\" : {},\n            \"acls\" : {\n                \"anonymous_rpc\" : {\"for\": \"NT AUTHORITY\\\\ANONYMOUS LOGON\", \"to\": \"DC=North,DC=sevenkingdoms,DC=local\", \"right\": \"ReadProperty\", \"inheritance\": \"All\"},\n                \"anonymous_rpc2\" : {\"for\": \"NT AUTHORITY\\\\ANONYMOUS LOGON\", \"to\": \"DC=North,DC=sevenkingdoms,DC=local\", \"right\": \"GenericExecute\", \"inheritance\": \"All\"}\n            },\n            \"users\" : {\n                \"arya.stark\" : {\n                    \"firstname\"   : \"Arya\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"Needle\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Arya Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"eddard.stark\" : {\n                    \"firstname\"   : \"Eddard\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"FightP3aceAndHonor!\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Eddard Stark\",\n                    \"groups\"      : [\"Stark\", \"Domain Admins\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"catelyn.stark\" : {\n                    \"firstname\"   : \"Catelyn\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"robbsansabradonaryarickon\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Catelyn Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"robb.stark\" : {\n                    \"firstname\"   : \"Robb\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"sexywolfy\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Robb Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"sansa.stark\" : {\n                    \"firstname\"   : \"Sansa\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"345ertdfg\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Sansa Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\",\n                    \"spns\"        : [\"HTTP/eyrie.north.sevenkingdoms.local\"]\n                },\n                \"brandon.stark\" : {\n                    \"firstname\"   : \"Brandon\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"iseedeadpeople\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Brandon Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"rickon.stark\" : {\n                    \"firstname\"   : \"Rickon\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"Winter2022\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Rickon Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"hodor\" : {\n                    \"firstname\"   : \"hodor\",\n                    \"surname\"     : \"hodor\",\n                    \"password\"    : \"hodor\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Brainless Giant\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"jon.snow\" : {\n                    \"firstname\"   : \"Jon\",\n                    \"surname\"     : \"Snow\",\n                    \"password\"    : \"iknownothing\",\n                    \"city\"        : \"Castel Black\",\n                    \"description\" : \"Jon Snow\",\n                    \"groups\"      : [\"Stark\", \"Night Watch\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\",\n                    \"spns\"        : [\"HTTP/thewall.north.sevenkingdoms.local\"]\n                },\n                \"samwell.tarly\" : {\n                    \"firstname\"   : \"Samwell\",\n                    \"surname\"     : \"Tarly\",\n                    \"password\"    : \"Heartsbane\",\n                    \"city\"        : \"Castel Black\",\n                    \"description\" : \"Samwell Tarly (Password : Heartsbane)\",\n                    \"groups\"      : [\"Night Watch\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"jeor.mormont\" : {\n                    \"firstname\"   : \"Jeor\",\n                    \"surname\"     : \"Mormont\",\n                    \"password\"    : \"_L0ngCl@w_\",\n                    \"city\"        : \"Castel Black\",\n                    \"description\" : \"Jeor Mormont\",\n                    \"groups\"      : [\"Night Watch\", \"Mormont\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"sql_svc\" : {\n                    \"firstname\"   : \"sql\",\n                    \"surname\"     : \"service\",\n                    \"password\"    : \"YouWillNotKerboroast1ngMeeeeee\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"sql service\",\n                    \"groups\"      : [],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\",\n                    \"spns\"        : [\"MSSQLSvc/castelblack.north.sevenkingdoms.local:1433\",\"MSSQLSvc/castelblack.north.sevenkingdoms.local\"]\n                }\n            }\n        },\n        \"sevenkingdoms.local\" : {\n            \"dc\": \"dc01\",\n            \"domain_password\" : \"8dCT-DJjgScp\",\n            \"netbios_name\": \"SEVENKINGDOMS\",\n            \"trust\" : \"essos.local\",\n            \"laps_path\": \"OU=Laps,DC=sevenkingdoms,DC=local\",\n            \"organisation_units\" : {\n                \"Vale\"        : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"IronIslands\" : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Riverlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Crownlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Stormlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Westerlands\" : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Reach\"       : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Dorne\"       : { \"path\" : \"DC=sevenkingdoms,DC=local\"}\n            },\n            \"groups\" : {\n                \"universal\" : {},\n                \"global\" : {\n                    \"Lannister\" : {\n                        \"managed_by\" : \"tywin.lannister\",\n                        \"path\" : \"OU=Westerlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"Baratheon\" : {\n                        \"managed_by\" : \"robert.baratheon\",\n                        \"path\" : \"OU=Stormlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"Small Council\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"DragonStone\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"KingsGuard\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"DragonRider\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    }\n                },\n                \"domainlocal\" : {\n                    \"AcrossTheNarrowSea\" : {\n                        \"path\" : \"CN=Users,DC=sevenkingdoms,DC=local\"\n                    }\n                }\n            },\n            \"multi_domain_groups_member\" : {\n                \"AcrossTheNarrowSea\" : [\n                    \"essos.local\\\\daenerys.targaryen\"\n                ]\n            },\n            \"acls\" : {\n                \"forcechangepassword_tywin_jaime\" : {\"for\": \"tywin.lannister\", \"to\": \"jaime.lannister\", \"right\": \"Ext-User-Force-Change-Password\", \"inheritance\": \"None\"},\n                \"GenericWrite_on_user_jaimie_joffrey\" : {\"for\": \"jaime.lannister\", \"to\": \"joffrey.baratheon\", \"right\": \"GenericWrite\", \"inheritance\": \"None\"},\n                \"Writedacl_joffrey_tyron\" : {\"for\": \"joffrey.baratheon\", \"to\": \"tyron.lannister\", \"right\": \"WriteDacl\", \"inheritance\": \"None\"},\n                \"self-self-membership-on-group_tyron_small_council\" : {\"for\": \"tyron.lannister\", \"to\": \"Small Council\", \"right\": \"Ext-Self-Self-Membership\", \"inheritance\": \"None\"},\n                \"addmember_smallcouncil_DragonStone\" : {\"for\": \"Small Council\", \"to\": \"DragonStone\", \"right\": \"Ext-Write-Self-Membership\", \"inheritance\": \"All\"},\n                \"write_owner_dragonstone_kingsguard\" : {\"for\": \"DragonStone\", \"to\": \"KingsGuard\", \"right\": \"WriteOwner\", \"inheritance\": \"None\"},\n                \"GenericAll_kingsguard_stanis\" : {\"for\": \"KingsGuard\", \"to\": \"stannis.baratheon\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_stanis_dc\" : {\"for\": \"stannis.baratheon\", \"to\": \"kingslanding$\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_group_acrrosdom_dc\" : {\"for\": \"AcrossTheNarrowSea\", \"to\": \"kingslanding$\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_varys_domadmin\" : {\"for\": \"lord.varys\", \"to\": \"Domain Admins\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_varys_domadmin_holder\" : {\"for\": \"lord.varys\", \"to\": \"CN=AdminSDHolder,CN=System,DC=sevenkingdoms,DC=local\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"WriteDACL_renly_Crownlands\" : {\"for\": \"renly.baratheon\", \"to\": \"OU=Crownlands,DC=sevenkingdoms,DC=local\", \"right\": \"WriteDacl\", \"inheritance\": \"None\"}\n            },\n            \"users\" : {\n                \"tywin.lannister\" : {\n                    \"firstname\"   : \"Tywin\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"powerkingftw135\",\n                    \"city\"        : \"Casterly Rock\",\n                    \"description\" : \"Tywin Lanister\",\n                    \"groups\"      : [\"Lannister\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"jaime.lannister\" : {\n                    \"firstname\"   : \"Jaime\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"cersei\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Jaime Lanister\",\n                    \"groups\"      : [\"Lannister\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"cersei.lannister\" : {\n                    \"firstname\"   : \"Cersei\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"il0vejaime\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Cersei Lanister\",\n                    \"groups\"      : [\"Lannister\",\"Baratheon\",\"Domain Admins\",\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"tyron.lannister\" : {\n                    \"firstname\"   : \"Tyron\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"Alc00L&S3x\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Tyron Lanister\",\n                    \"groups\"      : [\"Lannister\"],\n                    \"path\"        : \"OU=Westerlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"robert.baratheon\" : {\n                    \"firstname\"   : \"Robert\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"iamthekingoftheworld\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Robert Lanister\",\n                    \"groups\"      : [\"Baratheon\",\"Domain Admins\",\"Small Council\",\"Protected Users\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"joffrey.baratheon\" : {\n                    \"firstname\"   : \"Joffrey\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"1killerlion\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Joffrey Baratheon\",\n                    \"groups\"      : [\"Baratheon\",\"Lannister\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"renly.baratheon\" : {\n                    \"firstname\"   : \"Renly\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"lorastyrell\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Renly Baratheon\",\n                    \"groups\"      : [\"Baratheon\",\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"stannis.baratheon\" : {\n                    \"firstname\"   : \"Stannis\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"Drag0nst0ne\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Stannis Baratheon\",\n                    \"groups\"      : [\"Baratheon\",\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"petyer.baelish\" : {\n                    \"firstname\"   : \"Petyer\",\n                    \"surname\"     : \"Baelish\",\n                    \"password\"    : \"@littlefinger@\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Petyer Baelish\",\n                    \"groups\"      : [\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"lord.varys\" : {\n                    \"firstname\"   : \"Lord\",\n                    \"surname\"     : \"Varys\",\n                    \"password\"    : \"_W1sper_$\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Lord Varys\",\n                    \"groups\"      : [\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"maester.pycelle\" : {\n                    \"firstname\"   : \"Maester\",\n                    \"surname\"     : \"Pycelle\",\n                    \"password\"    : \"MaesterOfMaesters\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Maester Pycelle\",\n                    \"groups\"      : [\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                }\n            }\n        }\n    }\n}}"
  },
  {
    "path": "ad/GOAD/data/inventory",
    "content": "; GLOBAL CONFIG\n[all:vars]\n; domain_name : folder inside ad/\ndomain_name=GOAD\n\n; administrator user\nadmin_user=administrator\n\n; global settings inventory default value\nkeyboard_layouts=[\"en-US\", \"da-DK\", \"fr-FR\"]\n\n; modify this to add a default route\nadd_route=no\nroute_gateway=192.168.56.1\nroute_network=10.0.0.0/8\n\n; modify this to enable http proxy\nenable_http_proxy=no\nad_http_proxy=http://x.x.x.x:xxxx\nad_https_proxy=http://x.x.x.x:xxxx\n\n;force_dns_server\nforce_dns_server=no\ndns_server=1.1.1.1\n\n;dns server forwarder\ndns_server_forwarder=1.1.1.1\n\n; winrm connection (windows)\nansible_user=vagrant\nansible_password=vagrant\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n# ansible_winrm_transport=basic\n# ansible_port=5985\n\n; proxy settings (the lab need internet for some install, if you are behind a proxy you should set the proxy here)\nenable_http_proxy=no\nad_http_proxy=http://x.x.x.x:xxxx\nad_https_proxy=http://x.x.x.x:xxxx\n\n; LAB SCENARIO CONFIGURATION -----------------------------\n\n; computers inside domain (mandatory)\n; usage : build.yml, ad-relations.yml, ad-servers.yml, vulnerabilities.yml\n[domain]\ndc01\ndc02\ndc03\nsrv02\nsrv03\n\n[linux_domain]\n\n; domain controler (mandatory)\n; usage : ad-acl.yml, ad-data.yml, ad-relations.yml, laps.yml\n[dc]\ndc01\ndc02\ndc03\n\n; domain server to enroll (mandatory if you want servers)\n; usage : ad-data.yml, ad-servers.yml, laps.yml\n[server]\nsrv02\nsrv03\n\n; workstation to enroll (mandatory if you want workstation)\n; usage : ad-servers.yml, laps.yml\n[workstation]\n\n; parent domain controler (mandatory)\n; usage : ad-servers.yml\n[parent_dc]\ndc01\ndc03\n\n; child domain controler (need a fqdn child_name.parent_name)\n; usage : ad-servers.yml\n[child_dc]\ndc02\n\n; external trust, need domain trust entry in config (bidirectionnal)\n; usage : ad-trusts.yml\n[trust]\ndc01\ndc03\n\n; install adcs\n; usage : adcs.yml\n[adcs]\ndc01\nsrv03\n\n; install custom template (dc)\n; usage : adcs.yml\n[adcs_customtemplates]\ndc03\n\n; install iis with default website asp upload on 80\n; usage : servers.yml\n[iis]\nsrv02\n\n; install mssql\n; usage : servers.yml\n[mssql]\nsrv02\nsrv03\n\n; install mssql gui\n; usage : servers.yml\n[mssql_ssms]\nsrv02\n\n; install webdav \n[webdav]\nsrv02\nsrv03\n\n[laps_dc]\ndc03\n[laps_server]\nsrv03\n[laps_workstation]\n\n; allow computer update\n; usage : update.yml\n[update]\nsrv02\n\n; disable update\n; usage : update.yml\n[no_update]\ndc01\ndc02\ndc03\nsrv03\n\n; allow defender\n; usage : security.yml\n[defender_on]\ndc01\ndc02\ndc03\nsrv03\n\n; disable defender\n; usage : security.yml\n[defender_off]\nsrv02\n\n;stay empty until override\n[extensions]"
  },
  {
    "path": "ad/GOAD/data/inventory_disable_vagrant",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=administrator@sevenkingdoms.local ansible_password=8dCT-DJjgScp\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02 ansible_user=administrator@north.sevenkingdoms.local ansible_password=NgtI75cKV+Pu\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02 ansible_user=administrator@north.sevenkingdoms.local ansible_password=NgtI75cKV+Pu\n; ------------------------------------------------\n; essos.local\n; ------------------------------------------------\ndc03 ansible_host={{ip_range}}.12 dns_domain=dc03 dict_key=dc03 ansible_user=administrator@essos.local ansible_password=Ufe-bVXSx9rk\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc03 dict_key=srv03 ansible_user=administrator@essos.local ansible_password=Ufe-bVXSx9rk\n\n[all:vars]\n; domain_name : folder inside ad/\ndomain_name=GOAD\n\n; winrm connection (windows)\nansible_winrm_transport=ntlm\nansible_user=notused\nansible_password=notused\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n\n; LAB SCENARIO CONFIGURATION -----------------------------\n[domain]\ndc01\ndc02\nsrv02\ndc03\nsrv03\n"
  },
  {
    "path": "ad/GOAD/files/dc02/bot_rdp.ps1",
    "content": "# https://learn.microsoft.com/fr-fr/troubleshoot/windows-server/user-profiles-and-logon/turn-on-automatic-logon\nif(-not(query session robb.stark /server:castelblack)) {\n  #kill process if exist\n  Get-Process mstsc -IncludeUserName | Where {$_.UserName -eq \"NORTH\\robb.stark\"}|Stop-Process\n  #run the command\n  mstsc /v:castelblack\n}"
  },
  {
    "path": "ad/GOAD/files/dc02/sysvol_scripts/script.ps1",
    "content": "# fake script in netlogon with creds\n$task = '/c TODO'\n$taskName = \"fake task\"\n$user = \"NORTH\\jeor.mormont\"\n$password = \"_L0ngCl@w_\"\n\n# passwords in sysvol still ..."
  },
  {
    "path": "ad/GOAD/files/dc02/sysvol_scripts/secret.ps1",
    "content": "# cypher script\n# $domain=\"sevenkingdoms.local\"\n# $EncryptionKeyBytes = New-Object Byte[] 32\n# [Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($EncryptionKeyBytes)\n# $EncryptionKeyBytes | Out-File \"encryption.key\"\n# $EncryptionKeyData = Get-Content \"encryption.key\"\n# Read-Host -AsSecureString | ConvertFrom-SecureString -Key $EncryptionKeyData | Out-File -FilePath \"secret.encrypted\"\n\n# secret stored :\n$keyData = 177, 252, 228, 64, 28, 91, 12, 201, 20, 91, 21, 139, 255, 65, 9, 247, 41, 55, 164, 28, 75, 132, 143, 71, 62, 191, 211, 61, 154, 61, 216, 91\n$secret=\"76492d1116743f0423413b16050a5345MgB8AGkAcwBDACsAUwArADIAcABRAEcARABnAGYAMwA3AEEAcgBFAEIAYQB2AEEAPQA9AHwAZQAwADgANAA2ADQAMABiADYANAAwADYANgA1ADcANgAxAGIAMQBhAGQANQBlAGYAYQBiADQAYQA2ADkAZgBlAGQAMQAzADAANQAyADUAMgAyADYANAA3ADAAZABiAGEAOAA0AGUAOQBkAGMAZABmAGEANAAyADkAZgAyADIAMwA=\"\n\n# T.L."
  },
  {
    "path": "ad/GOAD/files/srv02/all/arya.txt",
    "content": "Subject: Quick Departure\n\nHey Arya,\n\nI hope this message finds you well. Something urgent has come up, and I have to leave for a while. Don't worry; I'll be back soon.\n\nI left a little surprise for you in your room – the sword You've named \"Needle.\" It felt fitting, given your skills. Take care of it, and it'll take care of you.\n\nI'll explain everything when I return. Until then, stay sharp, sis.\n\nBest,\nJohn"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/Default.aspx",
    "content": "﻿<%@ Page Language=\"C#\" AutoEventWireup=\"true\" CodeBehind=\"Default.aspx.cs\" Inherits=\"WebApp.Default\" %>\r\n\r\n<!DOCTYPE html>\r\n\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n<head runat=\"server\">\r\n    <title></title>\r\n</head>\r\n<body>\r\n    File uploader to the upload/ folder\r\n    <form id=\"form1\" runat=\"server\">\r\n        <div>\r\n            <asp:FileUpload ID=\"FileUpload1\" runat=\"server\" /><br/>\r\n            <asp:Button ID=\"Button1\" runat=\"server\" Text=\"Upload File\" OnClick=\"UploadFile\" /><br/>\r\n            <asp:Label ID=\"Label1\" runat=\"server\" Text=\"\"></asp:Label>\r\n        </div>\r\n    </form>\r\n</body>\r\n</html>"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/Web.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!--\r\n  For more information on how to configure your ASP.NET application, please visit\r\n  https://go.microsoft.com/fwlink/?LinkId=169433\r\n  -->\r\n<configuration>\r\n  <system.web>\r\n    <compilation targetFramework=\"4.7.2\" />\r\n    <httpRuntime targetFramework=\"4.7.2\" />\r\n  </system.web>\r\n  <system.codedom>\r\n    <compilers>\r\n      <compiler language=\"c#;cs;csharp\" extension=\".cs\" type=\"Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" warningLevel=\"4\" compilerOptions=\"/langversion:default /nowarn:1659;1699;1701\" />\r\n      <compiler language=\"vb;vbs;visualbasic;vbscript\" extension=\".vb\" type=\"Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" warningLevel=\"4\" compilerOptions=\"/langversion:default /nowarn:41008 /define:_MYTYPE=\\&quot;Web\\&quot; /optionInfer+\" />\r\n    </compilers>\r\n  </system.codedom>\r\n</configuration>\r\n<!--ProjectGuid: 2B11A106-027E-4619-8BFC-1997E60A510C-->"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/bin/roslyn/Microsoft.CSharp.Core.targets",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <Import Project=\"Microsoft.Managed.Core.targets\"/>\r\n\r\n  <Target Name=\"CoreCompile\"\r\n          Inputs=\"$(MSBuildAllProjects);\r\n                  @(Compile);\r\n                  @(_CoreCompileResourceInputs);\r\n                  $(ApplicationIcon);\r\n                  $(AssemblyOriginatorKeyFile);\r\n                  @(ReferencePathWithRefAssemblies);\r\n                  @(CompiledLicenseFile);\r\n                  @(LinkResource);\r\n                  @(EmbeddedDocumentation);\r\n                  $(Win32Resource);\r\n                  $(Win32Manifest);\r\n                  @(CustomAdditionalCompileInputs);\r\n                  $(ResolvedCodeAnalysisRuleSet);\r\n                  @(AdditionalFiles);\r\n                  @(EmbeddedFiles)\"\r\n          Outputs=\"@(DocFileItem);\r\n                   @(IntermediateAssembly);\r\n                   @(IntermediateRefAssembly);\r\n                   @(_DebugSymbolsIntermediatePath);\r\n                   $(NonExistentFile);\r\n                   @(CustomAdditionalCompileOutputs)\"\r\n          Returns=\"@(CscCommandLineArgs)\"\r\n          DependsOnTargets=\"$(CoreCompileDependsOn);_BeforeVBCSCoreCompile\">\r\n    <!-- These two compiler warnings are raised when a reference is bound to a different version\r\n             than specified in the assembly reference version number.  MSBuild raises the same warning in this case,\r\n             so the compiler warning would be redundant. -->\r\n    <PropertyGroup Condition=\"('$(TargetFrameworkVersion)' != 'v1.0') and ('$(TargetFrameworkVersion)' != 'v1.1')\">\r\n      <NoWarn>$(NoWarn);1701;1702</NoWarn>\r\n    </PropertyGroup>\r\n\r\n    <PropertyGroup>\r\n      <!-- To match historical behavior, when inside VS11+ disable the warning from csc.exe indicating that no sources were passed in-->\r\n      <NoWarn Condition=\"'$(BuildingInsideVisualStudio)' == 'true' AND '$(VisualStudioVersion)' != '' AND '$(VisualStudioVersion)' &gt; '10.0'\">$(NoWarn);2008</NoWarn>\r\n    </PropertyGroup>\r\n\r\n    <PropertyGroup>\r\n      <!-- If the user has specified AppConfigForCompiler, we'll use it. If they have not, but they set UseAppConfigForCompiler,\r\n                 then we'll use AppConfig -->\r\n      <AppConfigForCompiler Condition=\"'$(AppConfigForCompiler)' == '' AND '$(UseAppConfigForCompiler)' == 'true'\">$(AppConfig)</AppConfigForCompiler>\r\n\r\n      <!-- If we are targeting winmdobj we want to specifically the pdbFile property since we do not want it to collide with the output of winmdexp-->\r\n      <PdbFile Condition=\"'$(PdbFile)' == '' AND '$(OutputType)' == 'winmdobj' AND '$(_DebugSymbolsProduced)' == 'true'\">$(IntermediateOutputPath)$(TargetName).compile.pdb</PdbFile>\r\n    </PropertyGroup>\r\n\r\n    <!-- Condition is to filter out the _CoreCompileResourceInputs so that it doesn't pass in culture resources to the compiler -->\r\n    <Csc Condition=\"'%(_CoreCompileResourceInputs.WithCulture)' != 'true'\"\r\n         AdditionalLibPaths=\"$(AdditionalLibPaths)\"\r\n         AddModules=\"@(AddModules)\"\r\n         AdditionalFiles=\"@(AdditionalFiles)\"\r\n         AllowUnsafeBlocks=\"$(AllowUnsafeBlocks)\"\r\n         Analyzers=\"@(Analyzer)\"\r\n         ApplicationConfiguration=\"$(AppConfigForCompiler)\"\r\n         BaseAddress=\"$(BaseAddress)\"\r\n         CheckForOverflowUnderflow=\"$(CheckForOverflowUnderflow)\"\r\n         ChecksumAlgorithm=\"$(ChecksumAlgorithm)\"\r\n         CodeAnalysisRuleSet=\"$(ResolvedCodeAnalysisRuleSet)\"\r\n         CodePage=\"$(CodePage)\"\r\n         DebugType=\"$(DebugType)\"\r\n         DefineConstants=\"$(DefineConstants)\"\r\n         DelaySign=\"$(DelaySign)\"\r\n         DisabledWarnings=\"$(NoWarn)\"\r\n         DocumentationFile=\"@(DocFileItem)\"\r\n         EmbedAllSources=\"$(EmbedAllSources)\"\r\n         EmbeddedFiles=\"@(EmbeddedFiles)\"\r\n         EmitDebugInformation=\"$(DebugSymbols)\"\r\n         EnvironmentVariables=\"$(CscEnvironment)\"\r\n         ErrorEndLocation=\"$(ErrorEndLocation)\"\r\n         ErrorLog=\"$(ErrorLog)\"\r\n         ErrorReport=\"$(ErrorReport)\"\r\n         Features=\"$(Features)\"\r\n         FileAlignment=\"$(FileAlignment)\"\r\n         GenerateFullPaths=\"$(GenerateFullPaths)\"\r\n         HighEntropyVA=\"$(HighEntropyVA)\"\r\n         Instrument=\"$(Instrument)\"\r\n         KeyContainer=\"$(KeyContainerName)\"\r\n         KeyFile=\"$(KeyOriginatorFile)\"\r\n         LangVersion=\"$(LangVersion)\"\r\n         LinkResources=\"@(LinkResource)\"\r\n         MainEntryPoint=\"$(StartupObject)\"\r\n         ModuleAssemblyName=\"$(ModuleAssemblyName)\"\r\n         NoConfig=\"true\"\r\n         NoLogo=\"$(NoLogo)\"\r\n         NoStandardLib=\"$(NoCompilerStandardLib)\"\r\n         NoWin32Manifest=\"$(NoWin32Manifest)\"\r\n         Optimize=\"$(Optimize)\"\r\n         Deterministic=\"$(Deterministic)\"\r\n         PublicSign=\"$(PublicSign)\"\r\n         OutputAssembly=\"@(IntermediateAssembly)\"\r\n         OutputRefAssembly=\"@(IntermediateRefAssembly)\"\r\n         PdbFile=\"$(PdbFile)\"\r\n         Platform=\"$(PlatformTarget)\"\r\n         Prefer32Bit=\"$(Prefer32Bit)\"\r\n         PreferredUILang=\"$(PreferredUILang)\"\r\n         ProvideCommandLineArgs=\"$(ProvideCommandLineArgs)\"\r\n         References=\"@(ReferencePathWithRefAssemblies)\"\r\n         ReportAnalyzer=\"$(ReportAnalyzer)\"\r\n         Resources=\"@(_CoreCompileResourceInputs);@(CompiledLicenseFile)\"\r\n         ResponseFiles=\"$(CompilerResponseFile)\"\r\n         RuntimeMetadataVersion=\"$(RuntimeMetadataVersion)\"\r\n         SharedCompilationId=\"$(SharedCompilationId)\"\r\n         SkipCompilerExecution=\"$(SkipCompilerExecution)\"\r\n         Sources=\"@(Compile)\"\r\n         SubsystemVersion=\"$(SubsystemVersion)\"\r\n         TargetType=\"$(OutputType)\"\r\n         ToolExe=\"$(CscToolExe)\"\r\n         ToolPath=\"$(CscToolPath)\"\r\n         TreatWarningsAsErrors=\"$(TreatWarningsAsErrors)\"\r\n         UseHostCompilerIfAvailable=\"$(UseHostCompilerIfAvailable)\"\r\n         UseSharedCompilation=\"$(UseSharedCompilation)\"\r\n         Utf8Output=\"$(Utf8Output)\"\r\n         VsSessionGuid=\"$(VsSessionGuid)\"\r\n         WarningLevel=\"$(WarningLevel)\"\r\n         WarningsAsErrors=\"$(WarningsAsErrors)\"\r\n         WarningsNotAsErrors=\"$(WarningsNotAsErrors)\"\r\n         Win32Icon=\"$(ApplicationIcon)\"\r\n         Win32Manifest=\"$(Win32Manifest)\"\r\n         Win32Resource=\"$(Win32Resource)\"\r\n         PathMap=\"$(PathMap)\"\r\n         SourceLink=\"$(SourceLink)\">\r\n      <Output TaskParameter=\"CommandLineArgs\" ItemName=\"CscCommandLineArgs\" />\r\n    </Csc>\r\n\r\n    <ItemGroup>\r\n      <_CoreCompileResourceInputs Remove=\"@(_CoreCompileResourceInputs)\" />\r\n    </ItemGroup>\r\n\r\n    <CallTarget Targets=\"$(TargetsTriggeredByCompilation)\" Condition=\"'$(TargetsTriggeredByCompilation)' != ''\" />\r\n  </Target>\r\n</Project>"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/bin/roslyn/Microsoft.Managed.Core.targets",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <!--\r\n    Common targets for managed compilers.\r\n  -->\r\n  <UsingTask TaskName=\"Microsoft.CodeAnalysis.BuildTasks.MapSourceRoots\" AssemblyFile=\"$(MSBuildThisFileDirectory)Microsoft.Build.Tasks.CodeAnalysis.dll\" />\r\n\r\n  <Target Name=\"ShimReferencePathsWhenCommonTargetsDoesNotUnderstandReferenceAssemblies\"\r\n          BeforeTargets=\"CoreCompile\"\r\n          Condition=\"'@(ReferencePathWithRefAssemblies)' == ''\">\r\n    <!-- \r\n      FindReferenceAssembliesForReferences target in Common targets populate this item \r\n      since dev15.3. The compiler targets may be used (via NuGet package) on earlier MSBuilds. \r\n      If the ReferencePathWithRefAssemblies item is not populated, just use ReferencePaths \r\n      (implementation assemblies) as they are.\r\n      \r\n      Since XAML inner build runs CoreCompile directly (instead of Compile target),\r\n      it also doesn't invoke FindReferenceAssembliesForReferences listed in CompileDependsOn.\r\n      In that case we also populate ReferencePathWithRefAssemblies with implementation assemblies.\r\n    -->\r\n    <ItemGroup>\r\n      <ReferencePathWithRefAssemblies Include=\"@(ReferencePath)\" />\r\n    </ItemGroup>\r\n  </Target>\r\n\r\n  <Target Name=\"_BeforeVBCSCoreCompile\"\r\n          DependsOnTargets=\"ShimReferencePathsWhenCommonTargetsDoesNotUnderstandReferenceAssemblies\">\r\n    \r\n    <ItemGroup Condition=\"'$(TargetingClr2Framework)' == 'true'\">\r\n      <ReferencePathWithRefAssemblies>\r\n        <EmbedInteropTypes />\r\n      </ReferencePathWithRefAssemblies>\r\n    </ItemGroup>\r\n\r\n    <!-- Prefer32Bit was introduced in .NET 4.5. Set it to false if we are targeting 4.0 -->\r\n    <PropertyGroup Condition=\"('$(TargetFrameworkVersion)' == 'v4.0')\">\r\n      <Prefer32Bit>false</Prefer32Bit>\r\n    </PropertyGroup>\r\n\r\n    <!-- TODO: Remove this ItemGroup once it has been moved to \"_GenerateCompileInputs\" target in Microsoft.Common.CurrentVersion.targets.\r\n         https://github.com/dotnet/roslyn/issues/12223 -->\r\n    <ItemGroup Condition=\"('$(AdditionalFileItemNames)' != '')\">\r\n      <AdditionalFileItems Include=\"$(AdditionalFileItemNames)\" />\r\n      <AdditionalFiles Include=\"@(%(AdditionalFileItems.Identity))\" />\r\n    </ItemGroup>\r\n\r\n    <PropertyGroup Condition=\"'$(UseSharedCompilation)' == ''\">\r\n      <UseSharedCompilation>true</UseSharedCompilation>\r\n    </PropertyGroup>\r\n  </Target>\r\n\r\n  <!--\r\n    ========================\r\n    DeterministicSourcePaths\r\n    ========================\r\n    \r\n    Unless specified otherwise enable deterministic source root (PathMap) when building deterministically on CI server, but not for local builds.\r\n    In order for the debugger to find source files when debugging a locally built binary the PDB must contain original, unmapped local paths.\r\n  -->\r\n  <PropertyGroup>\r\n    <DeterministicSourcePaths Condition=\"'$(DeterministicSourcePaths)' == '' and '$(Deterministic)' == 'true' and '$(ContinuousIntegrationBuild)' == 'true'\">true</DeterministicSourcePaths>\r\n  </PropertyGroup>\r\n\r\n  <!--\r\n    ==========\r\n    SourceRoot\r\n    ==========\r\n\r\n    All source files of the project are expected to be located under one of the directories specified by SourceRoot item group.\r\n    This target collects all SourceRoots from various sources.\r\n\r\n    This target calculates final local path for each SourceRoot and sets SourceRoot.MappedPath metadata accordingly.\r\n    The final path is a path with deterministic prefix when DeterministicSourcePaths is true, and the original path otherwise.\r\n    In addition, the target validates and deduplicates the SourceRoot items.\r\n\r\n    InitializeSourceControlInformation is an msbuild target that ensures the SourceRoot items are populated from source control.\r\n    The target is available only if SourceControlInformationFeatureSupported is true.\r\n\r\n    A consumer of SourceRoot.MappedPath metadata, such as Source Link generator, shall depend on this target. \r\n  -->\r\n\r\n  <Target Name=\"InitializeSourceRootMappedPaths\"\r\n          DependsOnTargets=\"_InitializeSourceRootMappedPathsFromSourceControl\">\r\n\r\n    <ItemGroup Condition=\"'@(_MappedSourceRoot)' != ''\">\r\n      <_MappedSourceRoot Remove=\"@(_MappedSourceRoot)\" />\r\n    </ItemGroup>\r\n\r\n    <Microsoft.CodeAnalysis.BuildTasks.MapSourceRoots SourceRoots=\"@(SourceRoot)\" Deterministic=\"$(DeterministicSourcePaths)\">\r\n      <Output TaskParameter=\"MappedSourceRoots\" ItemName=\"_MappedSourceRoot\" />\r\n    </Microsoft.CodeAnalysis.BuildTasks.MapSourceRoots>\r\n\r\n    <ItemGroup>\r\n      <SourceRoot Remove=\"@(SourceRoot)\" />\r\n      <SourceRoot Include=\"@(_MappedSourceRoot)\" />\r\n    </ItemGroup>\r\n  </Target>\r\n\r\n  <!-- \r\n    Declare that target InitializeSourceRootMappedPaths that populates MappedPaths metadata on SourceRoot items is available.\r\n  -->\r\n  <PropertyGroup>\r\n    <SourceRootMappedPathsFeatureSupported>true</SourceRootMappedPathsFeatureSupported>\r\n  </PropertyGroup>\r\n\r\n  <!-- \r\n    If InitializeSourceControlInformation target isn't supported, we just continue without invoking that synchronization target. \r\n    We'll proceed with SourceRoot (and other source control properties) provided by the user (or blank).\r\n  -->\r\n  <Target Name=\"_InitializeSourceRootMappedPathsFromSourceControl\"\r\n          DependsOnTargets=\"InitializeSourceControlInformation\"\r\n          Condition=\"'$(SourceControlInformationFeatureSupported)' == 'true'\" />\r\n\r\n  <!-- \r\n    =======\r\n    PathMap\r\n    =======\r\n\r\n    If DeterministicSourcePaths is true sets PathMap based on SourceRoot.MappedPaths.\r\n\r\n    This target requires SourceRoot to be initialized in order to calculate the PathMap.\r\n    If SourceRoot doesn't contain any top-level roots an error is reported.\r\n  -->\r\n\r\n  <Target Name=\"_SetPathMapFromSourceRoots\"\r\n          DependsOnTargets=\"InitializeSourceRootMappedPaths\"\r\n          BeforeTargets=\"CoreCompile\"\r\n          Condition=\"'$(DeterministicSourcePaths)' == 'true'\">\r\n\r\n    <ItemGroup>\r\n      <_TopLevelSourceRoot Include=\"@(SourceRoot)\" Condition=\"'%(SourceRoot.NestedRoot)' == ''\"/>\r\n    </ItemGroup>\r\n\r\n    <PropertyGroup Condition=\"'@(_TopLevelSourceRoot)' != ''\">\r\n      <!-- TODO: Report error/warning if /pathmap doesn't cover all emitted source paths: https://github.com/dotnet/roslyn/issues/23969 -->\r\n\r\n      <!-- TODO: PathMap should accept and ignore empty mapping: https://github.com/dotnet/roslyn/issues/23523 -->\r\n      <PathMap Condition=\"'$(PathMap)' != ''\">,$(PathMap)</PathMap>\r\n\r\n      <!--\r\n        Prepend the SourceRoot.MappedPath values to PathMap, if it already has a value.\r\n        For each emitted source path the compiler applies the first mapping that matches the path.\r\n        PathMap values set previously will thus only be applied if the mapping provided by \r\n        SourceRoot.MappedPath doesn't match. Since SourceRoot.MappedPath is also used by SourceLink \r\n        preferring it over manually set PathMap ensures that PathMap is consistent with SourceLink.\r\n      \r\n        TODO: quote the paths to avoid misinterpreting ',' and '=' in them as separators, \r\n        but quoting doesn't currently work (see https://github.com/dotnet/roslyn/issues/22835).\r\n      -->\r\n      <PathMap>@(_TopLevelSourceRoot->'%(Identity)=%(MappedPath)', ',')$(PathMap)</PathMap>\r\n    </PropertyGroup>\r\n  </Target>\r\n\r\n</Project>"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/bin/roslyn/Microsoft.VisualBasic.Core.targets",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <Import Project=\"Microsoft.Managed.Core.targets\"/>\r\n\r\n  <Target Name=\"CoreCompile\"\r\n          Inputs=\"$(MSBuildAllProjects);\r\n                  @(Compile);\r\n                  @(_CoreCompileResourceInputs);\r\n                  $(ApplicationIcon);\r\n                  $(AssemblyOriginatorKeyFile);\r\n                  @(ReferencePathWithRefAssemblies);\r\n                  @(CompiledLicenseFile);\r\n                  @(LinkResource);\r\n                  @(EmbeddedDocumentation);\r\n                  $(Win32Resource);\r\n                  $(Win32Manifest);\r\n                  @(CustomAdditionalCompileInputs);\r\n                  $(ResolvedCodeAnalysisRuleSet);\r\n                  @(AdditionalFiles);\r\n                  @(EmbeddedFiles)\"\r\n          Outputs=\"@(DocFileItem);\r\n                   @(IntermediateAssembly);\r\n                   @(IntermediateRefAssembly);\r\n                   @(_DebugSymbolsIntermediatePath);\r\n                   $(NonExistentFile);\r\n                   @(CustomAdditionalCompileOutputs)\"\r\n          Returns=\"@(VbcCommandLineArgs)\"\r\n          DependsOnTargets=\"$(CoreCompileDependsOn);_BeforeVBCSCoreCompile\">\r\n    <PropertyGroup>\r\n      <_NoWarnings Condition=\"'$(WarningLevel)' == '0'\">true</_NoWarnings>\r\n      <_NoWarnings Condition=\"'$(WarningLevel)' == '1'\">false</_NoWarnings>\r\n    </PropertyGroup>\r\n\r\n    <PropertyGroup>\r\n      <!-- If we are targeting winmdobj we want to specifically the pdbFile property since we do not want it to collide with the output of winmdexp-->\r\n      <PdbFile Condition=\"'$(PdbFile)' == '' AND '$(OutputType)' == 'winmdobj' AND '$(DebugSymbols)' == 'true'\">$(IntermediateOutputPath)$(TargetName).compile.pdb</PdbFile>\r\n    </PropertyGroup>\r\n\r\n    <!-- Condition is to filter out the _CoreCompileResourceInputs so that it doesn't pass in culture resources to the compiler -->\r\n    <Vbc Condition=\"'%(_CoreCompileResourceInputs.WithCulture)' != 'true'\"\r\n         AdditionalLibPaths=\"$(AdditionalLibPaths)\"\r\n         AddModules=\"@(AddModules)\"\r\n         AdditionalFiles=\"@(AdditionalFiles)\"\r\n         Analyzers=\"@(Analyzer)\"\r\n         BaseAddress=\"$(BaseAddress)\"\r\n         ChecksumAlgorithm=\"$(ChecksumAlgorithm)\"\r\n         CodeAnalysisRuleSet=\"$(ResolvedCodeAnalysisRuleSet)\"\r\n         CodePage=\"$(CodePage)\"\r\n         DebugType=\"$(DebugType)\"\r\n         DefineConstants=\"$(FinalDefineConstants)\"\r\n         DelaySign=\"$(DelaySign)\"\r\n         DisabledWarnings=\"$(NoWarn)\"\r\n         DocumentationFile=\"@(DocFileItem)\"\r\n         EmbedAllSources=\"$(EmbedAllSources)\"\r\n         EmbeddedFiles=\"@(EmbeddedFiles)\"\r\n         EmitDebugInformation=\"$(DebugSymbols)\"\r\n         EnvironmentVariables=\"$(VbcEnvironment)\"\r\n         ErrorLog=\"$(ErrorLog)\"\r\n         ErrorReport=\"$(ErrorReport)\"\r\n         Features=\"$(Features)\"\r\n         FileAlignment=\"$(FileAlignment)\"\r\n         GenerateDocumentation=\"$(GenerateDocumentation)\"\r\n         HighEntropyVA=\"$(HighEntropyVA)\"\r\n         Imports=\"@(Import)\"\r\n         Instrument=\"$(Instrument)\"\r\n         KeyContainer=\"$(KeyContainerName)\"\r\n         KeyFile=\"$(KeyOriginatorFile)\"\r\n         LangVersion=\"$(LangVersion)\"\r\n         LinkResources=\"@(LinkResource)\"\r\n         MainEntryPoint=\"$(StartupObject)\"\r\n         ModuleAssemblyName=\"$(ModuleAssemblyName)\"\r\n         NoConfig=\"true\"\r\n         NoStandardLib=\"$(NoCompilerStandardLib)\"\r\n         NoVBRuntimeReference=\"$(NoVBRuntimeReference)\"\r\n         NoWarnings=\"$(_NoWarnings)\"\r\n         NoWin32Manifest=\"$(NoWin32Manifest)\"\r\n         Optimize=\"$(Optimize)\"\r\n         Deterministic=\"$(Deterministic)\"\r\n         PublicSign=\"$(PublicSign)\"\r\n         OptionCompare=\"$(OptionCompare)\"\r\n         OptionExplicit=\"$(OptionExplicit)\"\r\n         OptionInfer=\"$(OptionInfer)\"\r\n         OptionStrict=\"$(OptionStrict)\"\r\n         OptionStrictType=\"$(OptionStrictType)\"\r\n         OutputAssembly=\"@(IntermediateAssembly)\"\r\n         OutputRefAssembly=\"@(IntermediateRefAssembly)\"\r\n         PdbFile=\"$(PdbFile)\"\r\n         Platform=\"$(PlatformTarget)\"\r\n         Prefer32Bit=\"$(Prefer32Bit)\"\r\n         PreferredUILang=\"$(PreferredUILang)\"\r\n         ProvideCommandLineArgs=\"$(ProvideCommandLineArgs)\"\r\n         References=\"@(ReferencePathWithRefAssemblies)\"\r\n         RemoveIntegerChecks=\"$(RemoveIntegerChecks)\"\r\n         ReportAnalyzer=\"$(ReportAnalyzer)\"\r\n         Resources=\"@(_CoreCompileResourceInputs);@(CompiledLicenseFile)\"\r\n         ResponseFiles=\"$(CompilerResponseFile)\"\r\n         RootNamespace=\"$(RootNamespace)\"\r\n         RuntimeMetadataVersion=\"$(RuntimeMetadataVersion)\"\r\n         SdkPath=\"$(FrameworkPathOverride)\"\r\n         SharedCompilationId=\"$(SharedCompilationId)\"\r\n         SkipCompilerExecution=\"$(SkipCompilerExecution)\"\r\n         Sources=\"@(Compile)\"\r\n         SubsystemVersion=\"$(SubsystemVersion)\"\r\n         TargetCompactFramework=\"$(TargetCompactFramework)\"\r\n         TargetType=\"$(OutputType)\"\r\n         ToolExe=\"$(VbcToolExe)\"\r\n         ToolPath=\"$(VbcToolPath)\"\r\n         TreatWarningsAsErrors=\"$(TreatWarningsAsErrors)\"\r\n         UseHostCompilerIfAvailable=\"$(UseHostCompilerIfAvailable)\"\r\n         UseSharedCompilation=\"$(UseSharedCompilation)\"\r\n         Utf8Output=\"$(Utf8Output)\"\r\n         VBRuntimePath=\"$(VBRuntimePath)\"\r\n         Verbosity=\"$(VbcVerbosity)\"\r\n         VsSessionGuid=\"$(VsSessionGuid)\"\r\n         WarningsAsErrors=\"$(WarningsAsErrors)\"\r\n         WarningsNotAsErrors=\"$(WarningsNotAsErrors)\"\r\n         Win32Icon=\"$(ApplicationIcon)\"\r\n         Win32Manifest=\"$(Win32Manifest)\"\r\n         Win32Resource=\"$(Win32Resource)\"\r\n         VBRuntime=\"$(VBRuntime)\"\r\n         PathMap=\"$(PathMap)\"\r\n         SourceLink=\"$(SourceLink)\">\r\n      <Output TaskParameter=\"CommandLineArgs\" ItemName=\"VbcCommandLineArgs\" />\r\n    </Vbc>\r\n    <ItemGroup>\r\n      <_CoreCompileResourceInputs Remove=\"@(_CoreCompileResourceInputs)\" />\r\n    </ItemGroup>\r\n\r\n    <CallTarget Targets=\"$(TargetsTriggeredByCompilation)\" Condition=\"'$(TargetsTriggeredByCompilation)' != ''\" />\r\n  </Target>\r\n</Project>"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/bin/roslyn/VBCSCompiler.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <gcServer enabled=\"true\" />\r\n    <gcConcurrent enabled=\"false\" />\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n  <appSettings>\r\n    <!-- Number of seconds with no activity before the server times out and closes. \r\n         Set to -1 to never shut down the server. -->\r\n    <add key=\"keepalive\" value=\"600\" />\r\n  </appSettings>\r\n</configuration>"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/bin/roslyn/csc.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <gcServer enabled=\"true\" />\r\n    <gcConcurrent enabled=\"false\" />\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n</configuration>"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/bin/roslyn/csc.rsp",
    "content": "﻿# Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.\r\n\r\n# This file contains command-line options that the C#\r\n# command line compiler (CSC) will process as part\r\n# of every compilation, unless the \"/noconfig\" option\r\n# is specified. \r\n\r\n# Reference the common Framework libraries\r\n/r:Accessibility.dll\r\n/r:Microsoft.CSharp.dll\r\n/r:System.Configuration.dll\r\n/r:System.Configuration.Install.dll\r\n/r:System.Core.dll\r\n/r:System.Data.dll\r\n/r:System.Data.DataSetExtensions.dll\r\n/r:System.Data.Linq.dll\r\n/r:System.Data.OracleClient.dll\r\n/r:System.Deployment.dll\r\n/r:System.Design.dll\r\n/r:System.DirectoryServices.dll\r\n/r:System.dll\r\n/r:System.Drawing.Design.dll\r\n/r:System.Drawing.dll\r\n/r:System.EnterpriseServices.dll\r\n/r:System.Management.dll\r\n/r:System.Messaging.dll\r\n/r:System.Runtime.Remoting.dll\r\n/r:System.Runtime.Serialization.dll\r\n/r:System.Runtime.Serialization.Formatters.Soap.dll\r\n/r:System.Security.dll\r\n/r:System.ServiceModel.dll\r\n/r:System.ServiceModel.Web.dll\r\n/r:System.ServiceProcess.dll\r\n/r:System.Transactions.dll\r\n/r:System.Web.dll\r\n/r:System.Web.Extensions.Design.dll\r\n/r:System.Web.Extensions.dll\r\n/r:System.Web.Mobile.dll\r\n/r:System.Web.RegularExpressions.dll\r\n/r:System.Web.Services.dll\r\n/r:System.Windows.Forms.dll\r\n/r:System.Workflow.Activities.dll\r\n/r:System.Workflow.ComponentModel.dll\r\n/r:System.Workflow.Runtime.dll\r\n/r:System.Xml.dll\r\n/r:System.Xml.Linq.dll\r\n"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/bin/roslyn/csi.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n</configuration>"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/bin/roslyn/csi.rsp",
    "content": "﻿/r:System\r\n/r:System.Core\r\n/r:Microsoft.CSharp\r\n/r:System.ValueTuple.dll\r\n/u:System\r\n/u:System.IO\r\n/u:System.Collections.Generic\r\n/u:System.Console\r\n/u:System.Diagnostics\r\n/u:System.Dynamic\r\n/u:System.Linq\r\n/u:System.Linq.Expressions\r\n/u:System.Text\r\n/u:System.Threading.Tasks"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/bin/roslyn/vbc.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <gcServer enabled=\"true\" />\r\n    <gcConcurrent enabled=\"false\" />\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n</configuration>"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/bin/roslyn/vbc.rsp",
    "content": "﻿# Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.\r\n\r\n# This file contains command-line options that the VB\r\n# command line compiler (VBC) will process as part\r\n# of every compilation, unless the \"/noconfig\" option\r\n# is specified. \r\n\r\n# Reference the common Framework libraries\r\n/r:Accessibility.dll\r\n/r:System.Configuration.dll\r\n/r:System.Configuration.Install.dll\r\n/r:System.Data.dll\r\n/r:System.Data.OracleClient.dll\r\n/r:System.Deployment.dll\r\n/r:System.Design.dll\r\n/r:System.DirectoryServices.dll\r\n/r:System.dll\r\n/r:System.Drawing.Design.dll\r\n/r:System.Drawing.dll\r\n/r:System.EnterpriseServices.dll\r\n/r:System.Management.dll\r\n/r:System.Messaging.dll\r\n/r:System.Runtime.Remoting.dll\r\n/r:System.Runtime.Serialization.Formatters.Soap.dll\r\n/r:System.Security.dll\r\n/r:System.ServiceProcess.dll\r\n/r:System.Transactions.dll\r\n/r:System.Web.dll\r\n/r:System.Web.Mobile.dll\r\n/r:System.Web.RegularExpressions.dll\r\n/r:System.Web.Services.dll\r\n/r:System.Windows.Forms.dll\r\n/r:System.XML.dll\r\n\r\n/r:System.Workflow.Activities.dll\r\n/r:System.Workflow.ComponentModel.dll\r\n/r:System.Workflow.Runtime.dll\r\n/r:System.Runtime.Serialization.dll\r\n/r:System.ServiceModel.dll\r\n\r\n/r:System.Core.dll\r\n/r:System.Xml.Linq.dll\r\n/r:System.Data.Linq.dll\r\n/r:System.Data.DataSetExtensions.dll\r\n/r:System.Web.Extensions.dll\r\n/r:System.Web.Extensions.Design.dll\r\n/r:System.ServiceModel.Web.dll\r\n\r\n# Import System and Microsoft.VisualBasic\r\n/imports:System\r\n/imports:Microsoft.VisualBasic\r\n/imports:System.Linq\r\n/imports:System.Xml.Linq\r\n\r\n/optioninfer+\r\n"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/index.html",
    "content": "<html>\n    <head>\n    </head>\n    <body>\n        <p>Please follow <a href=\"/Default.aspx\">this link</a> to upload your files.</p>\n    </body>\n</html>"
  },
  {
    "path": "ad/GOAD/files/srv02/wwwroot/upload/.gitkeep",
    "content": ""
  },
  {
    "path": "ad/GOAD/providers/aws/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=8dCT-DJjgScp\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02 ansible_user=ansible ansible_password=NgtI75cKV+Pu\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02 ansible_user=ansible ansible_password=NgtI75cKV+Pu\n; ------------------------------------------------\n; essos.local\n; ------------------------------------------------\ndc03 ansible_host={{ip_range}}.12 dns_domain=dc03 dict_key=dc03 ansible_user=ansible ansible_password=Ufe-bVXSx9rk\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc03 dict_key=srv03 ansible_user=ansible ansible_password=978i2pF43UJ-\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/GOAD/providers/aws/linux.tf",
    "content": "# \"lx01\" = {\n#   name               = \"lx01\"\n#   linux_sku          = \"22_04-lts-gen2\"\n#   linux_version      = \"latest\"\n#   ami                = \"ami-04c332520bd9cedb4\"\n#   private_ip_address = \"{{ip_range}}.40\"\n#   password           = \"suppaP@ssw0rd$\"\n#   size               = \"t2.medium\"\n# }"
  },
  {
    "path": "ad/GOAD/providers/aws/windows.tf",
    "content": "# t2.medium = 2cpu / 4GB\n# t2.large  = 2cpu / 8GB\n# t2.xlarge = 4cpu / 16GB\n\"dc01\" = {\n  name               = \"dc01\"\n  domain             = \"sevenkingdoms.local\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCT-DJjgScp\"\n}\n\"dc02\" = {\n  name               = \"dc02\"\n  domain             = \"north.sevenkingdoms.local\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.11\"\n  password           = \"NgtI75cKV+Pu\"\n}\n\"dc03\" = {\n  name               = \"dc03\"\n  domain             = \"essos.local\"\n  windows_sku        = \"2016-Datacenter\"\n  ami                = \"ami-053492b4735046f1c\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.12\"\n  password           = \"Ufe-bVXSx9rk\"\n}\n\"srv02\" = {\n  name               = \"srv02\"\n  domain             = \"north.sevenkingdoms.local\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.22\"\n  password           = \"NgtI75cKV+Pu\"\n}\n\"srv03\" = {\n  name               = \"srv03\"\n  domain             = \"essos.local\"\n  windows_sku        = \"2016-Datacenter\"\n  ami                = \"ami-053492b4735046f1c\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.23\"\n  password           = \"978i2pF43UJ-\"\n}"
  },
  {
    "path": "ad/GOAD/providers/azure/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=8dCT-DJjgScp\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02 ansible_user=ansible ansible_password=NgtI75cKV+Pu\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02 ansible_user=ansible ansible_password=NgtI75cKV+Pu\n; ------------------------------------------------\n; essos.local\n; ------------------------------------------------\ndc03 ansible_host={{ip_range}}.12 dns_domain=dc03 dict_key=dc03 ansible_user=ansible ansible_password=Ufe-bVXSx9rk\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc03 dict_key=srv03 ansible_user=ansible ansible_password=978i2pF43UJ-\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/GOAD/providers/azure/linux.tf",
    "content": "# \"lx01\" = {\n#   name               = \"lx01\"\n#   linux_offer        = \"0001-com-ubuntu-server-jammy\"\n#   linux_sku          = \"22_04-lts-gen2\"\n#   linux_version      = \"latest\"\n#   private_ip_address = \"{{ip_range}}.40\"\n#   password           = \"suppaP@ssw0rd$\"\n#   size               = \"Standard_B2s\"\n# }"
  },
  {
    "path": "ad/GOAD/providers/azure/windows.tf",
    "content": "# Standard_B2s : 2 CPU / 4GB\n# Standard_B2ms : 2CPU / 8GB\n# Standard_B4ms : 4 cpu / 16 GB\n\"dc01\" = {\n  name               = \"dc01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCT-DJjgScp\"\n  size               = \"Standard_B2s\"\n}\n\"dc02\" = {\n  name               = \"dc02\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.11\"\n  password           = \"NgtI75cKV+Pu\"\n  size               = \"Standard_B2s\"\n}\n\"dc03\" = {\n  name               = \"dc03\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2016-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.12\"\n  password           = \"Ufe-bVXSx9rk\"\n  size               = \"Standard_B2s\"\n}\n\"srv02\" = {\n  name               = \"srv02\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.22\"\n  password           = \"NgtI75cKV+Pu\"\n  size               = \"Standard_B2s\"\n}\n\"srv03\" = {\n  name               = \"srv03\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2016-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.23\"\n  password           = \"978i2pF43UJ-\"\n  size               = \"Standard_B2s\"\n}\n"
  },
  {
    "path": "ad/GOAD/providers/ludus/config.yml",
    "content": "ludus:\n  - vm_name: \"{{ range_id }}-GOAD-DC01\"\n    hostname: \"{{ range_id }}-DC01\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 10\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-GOAD-DC02\"\n    hostname: \"{{ range_id }}-DC02\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 11\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-GOAD-DC03\"\n    hostname: \"{{ range_id }}-DC03\"\n    template: win2016-server-x64-template\n    vlan: 10\n    ip_last_octet: 12\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-GOAD-SRV02\"\n    hostname: \"{{ range_id }}-SRV02\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 22\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-GOAD-SRV03\"\n    hostname: \"{{ range_id }}-SRV03\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 23\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n"
  },
  {
    "path": "ad/GOAD/providers/ludus/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\n; ------------------------------------------------\n; essos.local\n; ------------------------------------------------\ndc03 ansible_host={{ip_range}}.12 dns_domain=dc03 dict_key=dc03\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc03 dict_key=srv03\n\n[all:vars]\nforce_dns_server=no\ndns_server={{ip_range}}.254\n\ndns_server_forwarder={{ip_range}}.254\n\nansible_user=localuser\nansible_password=password"
  },
  {
    "path": "ad/GOAD/providers/proxmox/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\n; ------------------------------------------------\n; essos.local\n; ------------------------------------------------\ndc03 ansible_host={{ip_range}}.12 dns_domain=dc03 dict_key=dc03\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc03 dict_key=srv03\n\n[all:vars]\nforce_dns_server=yes\ndns_server={{ip_range}}.1\n\n"
  },
  {
    "path": "ad/GOAD/providers/proxmox/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"DC01\"\n  desc               = \"DC01 - windows server 2019 - {{ip_range}}.10\"\n  cores              = 2\n  memory             = 3096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.10/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"dc02\" = {\n  name               = \"DC02\"\n  desc               = \"DC02 - windows server 2019 - {{ip_range}}.11\"\n  cores              = 2\n  memory             = 3096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.11/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"dc03\" = {\n  name               = \"DC03\"\n  desc               = \"DC03 - windows server 2016 - {{ip_range}}.12\"\n  cores              = 2\n  memory             = 3096\n  clone              = \"WinServer2016_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.12/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"srv02\" = {\n  name               = \"SRV02\"\n  desc               = \"SRV02 - windows server 2019 - {{ip_range}}.22\"\n  cores              = 2\n  memory             = 6240\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.22/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"srv03\" = {\n  name               = \"SRV03\"\n  desc               = \"SRV03 - windows server 2016 - {{ip_range}}.23\"\n  cores              = 2\n  memory             = 5120\n  clone              = \"WinServer2016_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.23/24\"\n  gateway            = \"{{ip_range}}.1\"\n}"
  },
  {
    "path": "ad/GOAD/providers/virtualbox/Vagrantfile",
    "content": "boxes = [\n  # windows server 2019\n  { :name => \"GOAD-DC01\",  :ip => \"{{ip_range}}.10\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-DC02\",  :ip => \"{{ip_range}}.11\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2016\n  { :name => \"GOAD-DC03\",  :ip => \"{{ip_range}}.12\", :box => \"StefanScherer/windows_2016\", :box_version => \"2017.12.14\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-SRV02\", :ip => \"{{ip_range}}.22\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 6000},\n  # windows server 2016\n  { :name => \"GOAD-SRV03\", :ip => \"{{ip_range}}.23\", :box => \"StefanScherer/windows_2016\", :box_version => \"2019.02.14\", :os => \"windows\", :cpus => 2, :mem => 5000}\n]"
  },
  {
    "path": "ad/GOAD/providers/virtualbox/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\n; ------------------------------------------------\n; essos.local\n; ------------------------------------------------\ndc03 ansible_host={{ip_range}}.12 dns_domain=dc03 dict_key=dc03\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc03 dict_key=srv03\n"
  },
  {
    "path": "ad/GOAD/providers/vmware/Vagrantfile",
    "content": "boxes = [\n  # windows server 2019\n  { :name => \"GOAD-DC01\",  :ip => \"{{ip_range}}.10\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-DC02\",  :ip => \"{{ip_range}}.11\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2016\n  { :name => \"GOAD-DC03\",  :ip => \"{{ip_range}}.12\", :box => \"StefanScherer/windows_2016\", :box_version => \"2017.12.14\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-SRV02\", :ip => \"{{ip_range}}.22\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 6000},\n  # windows server 2016\n  { :name => \"GOAD-SRV03\", :ip => \"{{ip_range}}.23\", :box => \"StefanScherer/windows_2016\", :box_version => \"2019.02.14\", :os => \"windows\", :cpus => 2, :mem => 5000}\n]"
  },
  {
    "path": "ad/GOAD/providers/vmware/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\n; ------------------------------------------------\n; essos.local\n; ------------------------------------------------\ndc03 ansible_host={{ip_range}}.12 dns_domain=dc03 dict_key=dc03\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc03 dict_key=srv03\n"
  },
  {
    "path": "ad/GOAD/providers/vmware_esxi/Vagrantfile",
    "content": "boxes = [\n  # windows server 2019\n  { :name => \"GOAD-DC01\",  :ip => \"{{ip_range}}.10\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-DC02\",  :ip => \"{{ip_range}}.11\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2016\n  { :name => \"GOAD-DC03\",  :ip => \"{{ip_range}}.12\", :box => \"StefanScherer/windows_2016\", :box_version => \"2017.12.14\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-SRV02\", :ip => \"{{ip_range}}.22\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 6000},\n  # windows server 2016\n  { :name => \"GOAD-SRV03\", :ip => \"{{ip_range}}.23\", :box => \"StefanScherer/windows_2016\", :box_version => \"2019.02.14\", :os => \"windows\", :cpus => 2, :mem => 5000}\n]"
  },
  {
    "path": "ad/GOAD/providers/vmware_esxi/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\n; ------------------------------------------------\n; essos.local\n; ------------------------------------------------\ndc03 ansible_host={{ip_range}}.12 dns_domain=dc03 dict_key=dc03\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc03 dict_key=srv03\n"
  },
  {
    "path": "ad/GOAD/scripts/archives/acl.ps1",
    "content": "# https://github.com/davidprowe/BadBlood/blob/master/AD_OU_SetACL/Full%20Control%20Permissions.ps1\nImport-Module ActiveDirectory\nSet-Location AD:\n\n###########################################################################################################\n# SetAcl  $for ---- $right ----> $to\n###########################################################################################################\nFunction SetAcl($for, $to, $right, $inheritance)\n{\n    $forSID = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser $for).SID\n    $objOU = ($to).DistinguishedName\n    $objAcl = get-acl $objOU\n    # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectoryrights?view=dotnet-plat-ext-5.0\n    $adRight =  [System.DirectoryServices.ActiveDirectoryRights] $right # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectoryrights?view=dotnet-plat-ext-5.0\n    $type =  [System.Security.AccessControl.AccessControlType] \"Allow\" # https://docs.microsoft.com/fr-fr/dotnet/api/system.security.accesscontrol.accesscontroltype?view=dotnet-plat-ext-5.0\n    $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] $inheritance # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectorysecurityinheritance?view=dotnet-plat-ext-5.0\n    $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $forSID,$adRight,$type,$inheritanceType\n    $objAcl.AddAccessRule($ace)\n    Set-Acl -AclObject $objAcl -path $objOU\n}\n\n# https://jorgequestforknowledge.wordpress.com/2014/08/20/powershell-and-dacls-in-ad-adding-ace-for-some-extended-right-on-some-object/\nFunction SetAclExtended($for, $to, $right, $extendedRightGUID, $inheritance)\n{\n    $forSID = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser $for).SID\n    $objOU = ($to).DistinguishedName\n    $objAcl = get-acl $objOU\n    # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectoryrights?view=dotnet-plat-ext-5.0\n    $adRight =  [System.DirectoryServices.ActiveDirectoryRights] $right # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectoryrights?view=dotnet-plat-ext-5.0\n    $type =  [System.Security.AccessControl.AccessControlType] \"Allow\" # https://docs.microsoft.com/fr-fr/dotnet/api/system.security.accesscontrol.accesscontroltype?view=dotnet-plat-ext-5.0\n    $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] $inheritance # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectorysecurityinheritance?view=dotnet-plat-ext-5.0\n\n    $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $forSID,$adRight,$type,$extendedRightGUID,$inheritanceType\n    $objAcl.AddAccessRule($ace)\n    Set-Acl -AclObject $objAcl -path $objOU\n}\n\n## acl values :\n# AccessSystemSecurity\n# CreateChild\n# Delete\n# DeleteChild\n# DeleteTree\n# ExtendedRight\n# GenericAll\n# GenericExecute\n# GenericRead\n# GenericWrite\n# ListChildren\n# ListObject\n# ReadControl\n# ReadProperty\n# Self\n# Synchronize\n# WriteDacl\n# WriteOwner\n# WriteProperty \n\n## extend rights\n# \"00299570-246d-11d0-a768-00aa006e0529\" {$right = \"User-Force-Change-Password\"}\n# \"45ec5156-db7e-47bb-b53f-dbeb2d03c40\"  {$right = \"Reanimate-Tombstones\"}\n# \"bf9679c0-0de6-11d0-a285-00aa003049e2\" {$right = \"Self-Membership\"}\n# \"ba33815a-4f93-4c76-87f3-57574bff8109\" {$right = \"Manage-SID-History\"}\n# \"1131f6ad-9c07-11d1-f79f-00c04fc2dcd2\" {$right = \"DS-Replication-Get-Changes-All\"}\n\n# ACL abuse scenarios\n# https://sensepost.com/blog/2020/ace-to-rce/\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces\n# https://adsecurity.org/?p=3658\n\n# genericall-on-user\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#genericall-on-user\nSetAcl (Get-ADUser \"tywin.lannister\") (Get-ADUser \"cersei.lannister\") \"GenericAll\" \"None\"\n\n# genericall-on-group\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#genericall-on-group\nSetAcl (Get-ADUser \"lord.varys\") (Get-ADGroup \"Domain Admins\") \"GenericAll\" \"None\"\n\n# genericall-genericwrite-write-on-computer\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#genericall-genericwrite-write-on-computer\nSetAcl (Get-ADUser \"stannis.baratheon\") (Get-ADComputer \"kingslanding\") \"GenericAll\" \"None\"\n\n# writeproperty-on-group\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#writeproperty-on-group\nSetAcl (Get-ADUser \"petyer.baelish\") (Get-ADGroup \"Domain Admins\") \"WriteProperty\" \"All\"\n\n# self-self-membership-on-group\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#self-self-membership-on-group\nSetAclExtended (Get-ADUser \"tyron.lannister\") (Get-ADGroup \"Domain Admins\") \"Self\" \"bf9679c0-0de6-11d0-a285-00aa003049e2\" \"None\"\n\n# writeproperty-self-membership\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#writeproperty-self-membership\nSetAclExtended (Get-ADUser \"stannis.baratheon\") (Get-ADGroup \"Domain Admins\") \"WriteProperty\" \"bf9679c0-0de6-11d0-a285-00aa003049e2\" \"All\"\n\n# forcechangepassword\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#forcechangepassword\n# https://docs.microsoft.com/fr-fr/windows/win32/adschema/r-user-change-password\nSetAclExtended (Get-ADUser \"tywin.lannister\") (Get-ADUser \"jaime.lannister\") \"ExtendedRight\" \"00299570-246d-11d0-a768-00aa006e0529\" \"None\"\n\n# write owner on group\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#writeowner-on-group\nSetAcl (Get-ADUser \"maester.pycelle\") (Get-ADGroup \"Domain Admins\") \"WriteOwner\" \"None\"\n\n# genericwrite-on-user\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#genericwrite-on-user\nSetAcl (Get-ADUser \"jaime.lannister\") (Get-ADUser \"cersei.lannister\") \"GenericWrite\" \"None\"\n\n# writedacl-writeowner\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#writedacl-writeowner\nSetAcl (Get-ADUser \"tywin.lannister\") (Get-ADGroup \"Small Council\") \"WriteDacl\" \"None\"\n"
  },
  {
    "path": "ad/GOAD/scripts/archives/anonymous_ldap.ps1",
    "content": "$anonymousId = New-Object System.Security.Principal.NTAccount \"NT AUTHORITY\\ANONYMOUS LOGON\"\n$secInheritanceAll = [System.DirectoryServices.ActiveDirectorySecurityInheritance] \"All\"\n$Ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $anonymousId,\"ReadProperty, GenericExecute\",\"Allow\",$secInheritanceAll\n$Acl = Get-Acl -Path \"AD:$($node.DCPathEnd)\"\n$Acl.AddAccessRule($Ace)\nSet-Acl -Path \"AD:$($node.DCPathEnd)\" -AclObject $Acl"
  },
  {
    "path": "ad/GOAD/scripts/archives/kerberoasting.ps1",
    "content": "Set-ADUser -Identity \"jon.snow\" -ServicePrincipalNames @{Add='HTTP/thewallserver'}"
  },
  {
    "path": "ad/GOAD/scripts/archives/rbcd.ps1",
    "content": "# TODO"
  },
  {
    "path": "ad/GOAD/scripts/archives/unconstrained_delegation.ps1",
    "content": "Get-ADComputer -Identity \"bravoos\" | Set-ADAccountControl -TrustedForDelegation $true"
  },
  {
    "path": "ad/GOAD/scripts/asrep_roasting.ps1",
    "content": "Get-ADUser -Identity \"brandon.stark\" | Set-ADAccountControl -DoesNotRequirePreAuth:$true"
  },
  {
    "path": "ad/GOAD/scripts/asrep_roasting2.ps1",
    "content": "Get-ADUser -Identity \"missandei\" | Set-ADAccountControl -DoesNotRequirePreAuth:$true"
  },
  {
    "path": "ad/GOAD/scripts/constrained_delegation_kerb_only.ps1",
    "content": "# https://www.thehacker.recipes/ad/movement/kerberos/delegations/constrained#without-protocol-transition\nSet-ADComputer -Identity \"castelblack$\" -ServicePrincipalNames @{Add='HTTP/winterfell.north.sevenkingdoms.local'}\nSet-ADComputer -Identity \"castelblack$\" -Add @{'msDS-AllowedToDelegateTo'=@('HTTP/winterfell.north.sevenkingdoms.local','HTTP/winterfell')}\n# Set-ADComputer -Identity \"castelblack$\" -Add @{'msDS-AllowedToDelegateTo'=@('CIFS/winterfell.north.sevenkingdoms.local','CIFS/winterfell')}"
  },
  {
    "path": "ad/GOAD/scripts/constrained_delegation_use_any.ps1",
    "content": "Set-ADUser -Identity \"jon.snow\" -ServicePrincipalNames @{Add='CIFS/thewall.north.sevenkingdoms.local'}\nGet-ADUser -Identity \"jon.snow\" | Set-ADAccountControl -TrustedToAuthForDelegation $true\nSet-ADUser -Identity \"jon.snow\" -Add @{'msDS-AllowedToDelegateTo'=@('CIFS/winterfell.north.sevenkingdoms.local','CIFS/winterfell')}"
  },
  {
    "path": "ad/GOAD/scripts/gpo_abuse.ps1",
    "content": "Install-WindowsFeature -Name GPMC\r\n$gpo_exist = Get-GPO -Name \"StarkWallpaper\" -erroraction ignore\r\n\r\nif ($gpo_exist) {\r\n    # Do nothing\r\n    #Remove-GPO -Name \"StarkWallpaper\"\r\n    #Remove the link of the GPO Remove-StarkWallpaper if it exists\r\n    #Remove-GPLink -Name \"StarkWallpaper\" -Target \"DC=north,DC=sevenkingdoms,DC=local\" -erroraction 'silentlycontinue'\r\n} else {\r\n    New-GPO -Name \"StarkWallpaper\" -comment \"Change Wallpaper\"\r\n    New-GPLink -Name \"StarkWallpaper\" -Target \"DC=north,DC=sevenkingdoms,DC=local\"\r\n\r\n    #https://www.thewindowsclub.com/set-desktop-wallpaper-using-group-policy-and-registry-editor\r\n    Set-GPRegistryValue -Name \"StarkWallpaper\" -key \"HKEY_CURRENT_USER\\Control Panel\\Colors\" -ValueName Background -Type String -Value \"100 175 200\"\r\n    #Set-GPPrefRegistryValue -Name \"StarkWallpaper\" -Context User -Action Create -Key \"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\" -ValueName Wallpaper -Type String -Value \"C:\\tmp\\GOAD.png\"\r\n\r\n    Set-GPRegistryValue -Name \"StarkWallpaper\" -key \"HKEY_CURRENT_USER\\Control Panel\\Desktop\" -ValueName Wallpaper -Type String -Value \"\"\r\n    #Set-GPPrefRegistryValue -Name \"StarkWallpaper\" -Context User -Action Create -Key \"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\" -ValueName WallpaperStyle -Type String -Value \"4\"\r\n\r\n    Set-GPRegistryValue -Name \"StarkWallpaper\" -Key \"HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon\" -ValueName SyncForegroundPolicy -Type DWORD -Value 1\r\n\r\n    # Allow samwell.tarly to Edit Settings of the GPO\r\n    # https://learn.microsoft.com/en-us/powershell/module/grouppolicy/set-gppermission?view=windowsserver2022-ps\r\n    Set-GPPermissions -Name \"StarkWallpaper\" -PermissionLevel GpoEditDeleteModifySecurity -TargetName \"samwell.tarly\" -TargetType \"User\"\r\n}"
  },
  {
    "path": "ad/GOAD/scripts/ntlm_relay.ps1",
    "content": "$task = '/c powershell New-PSDrive -Name \"Public\" -PSProvider \"FileSystem\" -Root \"\\\\Meren\\Private\"'\n$repeat = (New-TimeSpan -Minutes 5)\n$taskName = \"ntlm_bot\"\n$user = \"north.sevenkingdoms.local\\eddard.stark\"\n$password = \"FightP3aceAndHonor!\"\n\n$action = New-ScheduledTaskAction -Execute \"cmd.exe\" -Argument \"$task\"\n$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat\n$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd\n\n$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName }\nif($taskExists) {\n    Unregister-ScheduledTask -TaskName $taskName -Confirm:$false\n}\nRegister-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings\n"
  },
  {
    "path": "ad/GOAD/scripts/rdp_scheduler.ps1",
    "content": "$task = '/c powershell c:\\setup\\bot_rdp.ps1'\n$repeat = (New-TimeSpan -Minutes 1)\n$taskName = \"connect_bot\"\n$user = \"north\\robb.stark\"\n$password = \"sexywolfy\"\n$action = New-ScheduledTaskAction -Execute \"cmd.exe\" -Argument \"$task\"\n$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat\n$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd\n#$settings.CimInstanceProperties.Item('MultipleInstances').Value = 3   # 3 corresponds to 'Stop the existing instance'\n\n$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName }\nif($taskExists) {\n    Unregister-ScheduledTask -TaskName $taskName -Confirm:$false\n}\nRegister-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings"
  },
  {
    "path": "ad/GOAD/scripts/responder.ps1",
    "content": "$task = '/c powershell New-PSDrive -Name \"Public\" -PSProvider \"FileSystem\" -Root \"\\\\Bravos\\private\"'\n$repeat = (New-TimeSpan -Minutes 2)\n$taskName = \"responder_bot\"\n$user = \"north.sevenkingdoms.local\\robb.stark\"\n$password = \"sexywolfy\"\n\n$action = New-ScheduledTaskAction -Execute \"cmd.exe\" -Argument \"$task\"\n$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat\n$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd\n\n$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName }\nif($taskExists) {\n    Unregister-ScheduledTask -TaskName $taskName -Confirm:$false\n}\nRegister-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings\n"
  },
  {
    "path": "ad/GOAD/scripts/sidhistory.ps1",
    "content": "netdom trust sevenkingdoms.local /d:essos.local /enablesidhistory:yes"
  },
  {
    "path": "ad/GOAD/scripts/unconstrained_delegation_user.ps1",
    "content": "Get-ADUser -Identity \"sansa.stark\" | Set-ADAccountControl -TrustedForDelegation $true"
  },
  {
    "path": "ad/GOAD-Light/README.md",
    "content": "# GOAD-Light\n\n![GOAD Light overview](../../docs/img/GOAD-Light_schema.png)\n\nThis is a light version of goad without the essos domain. This lab was build for computer with less performance.\nMissing scenarios:\n- cross forest exploitation (no more external forest)\n- mssql trusted link\n- some old computer vulnerabilities (zero logon, petitpotam unauthent,...)\n- ESC4, ESC2/3\n\n### Servers\nThis lab is actually composed of three virtual machines:\n- **kingslanding** : DC01  running on Windows Server 2019 (with windefender enabled by default)\n- **winterfell**   : DC02  running on Windows Server 2019 (with windefender enabled by default)\n- **castelblack**  : SRV02 running on Windows Server 2019 (with windefender **disabled** by default)\n\n#### domain : north.sevenkingdoms.local\n- **winterfell**     : DC01\n- **castelblack**    : SRV02 : MSSQL / IIS\n\n#### domain : sevenkingdoms.local\n- **kingslanding**   : DC02\n\n\nThe lab setup is automated using vagrant and ansible automation tools.\nYou can change the vm version in the Vagrantfile according to Stefan Scherer vagrant repository : https://app.vagrantup.com/StefanScherer\n\n\n### Users/Groups and associated vulnerabilites/scenarios\n\n- You can find a lot of the available scenarios on [https://mayfly277.github.io/categories/ad/](https://mayfly277.github.io/categories/ad/)\n\nNORTH.SEVENKINGDOMS.LOCAL\n- STARKS:              RDP on WINTERFELL AND CASTELBLACK\n  - arya.stark:        Execute as user on mssql\n  - eddard.stark:      DOMAIN ADMIN NORTH/ (bot 5min) LLMRN request to do NTLM relay with responder\n  - catelyn.stark:     \n  - robb.stark:        bot (3min) RESPONDER LLMR\n  - sansa.stark:       \n  - brandon.stark:     ASREP_ROASTING\n  - rickon.stark:      \n  - theon.greyjoy:\n  - jon.snow:          mssql admin / KERBEROASTING / group cross domain / mssql trusted link\n  - hodor:             PASSWORD SPRAY (user=password)\n- NIGHT WATCH:         RDP on CASTELBLACK\n  - samwell.tarly:     Password in ldap description / mssql execute as login\n                       GPO abuse (Edit Settings on \"STARKWALLPAPER\" GPO)\n  - jon.snow:          (see starks)\n  - jeor.mormont:      (see mormont)\n- MORMONT:             RDP on CASTELBLACK\n  - jeor.mormont:      ACL writedacl-writeowner on group Night Watch\n- AcrossTheSea :       cross forest group\n\nSEVENKINGDOMS.LOCAL\n- LANISTERS\n  - tywin.lannister:   ACL forcechangepassword on jaime.lanister\n  - jaime.lannister:   ACL genericwrite-on-user joffrey.baratheon\n  - tyron.lannister:   ACL self-self-membership-on-group Small Council\n  - cersei.lannister:  DOMAIN ADMIN SEVENKINGDOMS\n- BARATHEON:           RDP on KINGSLANDING\n  - robert.baratheon:  DOMAIN ADMIN SEVENKINGDOMS\n  - joffrey.baratheon: ACL Write DACL on tyron.lannister\n  - renly.baratheon:\n  - stannis.baratheon: ACL genericall-on-computer kingslanding / ACL writeproperty-self-membership Domain Admins\n- SMALL COUNCIL :      ACL add Member to group dragon stone / RDP on KINGSLANDING\n  - petyer.baelish:    ACL writeproperty-on-group Domain Admins\n  - lord.varys:        ACL genericall-on-group Domain Admins / Acrossthenarrossea\n  - maester.pycelle:   ACL write owner on group Domain Admins\n- DRAGONSTONE :        ACL Write Owner on KINGSGUARD\n- KINGSGUARD :         ACL generic all on user stannis.baratheon\n- AccorsTheNarrowSea:       cross forest group\n\n\n### Computers Users and group permissions\n\n- SEVENKINGDOMS\n  - DC01 : kingslanding.sevenkingdoms.local (Windows Server 2019) (SEVENKINGDOMS DC)\n    - Admins : robert.baratheon (U), cersei.lannister (U)\n    - RDP: Small Council (G)\n\n- NORTH\n  - DC02 : winterfell.north.sevenkingdoms.local (Windows Server 2019) (NORTH DC)\n    - Admins : eddard.stark (U), catelyn.stark (U), robb.stark (U)\n    - RDP: Stark(G)\n\n  - SRV02 : castelblack.essos.local (Windows Server 2019) (IIS, MSSQL, SMB share)\n    - Admins: jeor.mormont (U)\n    - RDP: Night Watch (G), Mormont (G), Stark (G)\n    - IIS : allow asp upload, run as NT Authority/network\n    - MSSQL:\n      - admin : jon.snow\n      - impersonate : \n        - execute as login : samwel.tarlly -> sa\n        - execute as user : arya.stark -> dbo\n"
  },
  {
    "path": "ad/GOAD-Light/data/config.json",
    "content": "{\n\"lab\" : {\n    \"hosts\" : {\n        \"dc01\" : {\n            \"hostname\" : \"kingslanding\",\n            \"type\" : \"dc\",\n            \"local_admin_password\": \"8dCT-DJjgScp\",\n            \"domain\" : \"sevenkingdoms.local\",\n            \"path\" : \"DC=sevenkingdoms,DC=local\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"sevenkingdoms\\\\robert.baratheon\",\n                    \"sevenkingdoms\\\\cersei.lannister\",\n                    \"sevenkingdoms\\\\DragonRider\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"sevenkingdoms\\\\Small Council\",\n                    \"sevenkingdoms\\\\Baratheon\"\n                ]\n            },\n            \"scripts\" : [],\n            \"vulns\" : [\"disable_firewall\", \"directory\", \"files\", \"adcs_templates\"],\n            \"vulns_vars\" : {\n                \"directory\": {\n                    \"setup\": \"c:\\\\setup\"\n                },\n                \"files\" : {\n                    \"template\" : {\n                        \"src\" : \"dc01/templates/\",\n                        \"dest\" : \"C:\\\\setup\\\\\"\n                    }\n                },\n                \"adcs_templates\": {\n                    \"ESC1\": {\n                        \"template_name\" : \"ESC1\",\n                        \"template_file\" : \"C:\\\\setup\\\\ESC1.json\"\n                    }\n                }\n            },\n            \"security\": [\"account_is_sensitive\"],\n            \"security_vars\": {\n                \"account_is_sensitive\" : { \"renly\": {\"account\" : \"renly.baratheon\"} }\n            }\n        },\n        \"dc02\" : {\n            \"hostname\" : \"winterfell\",\n            \"type\" : \"dc\",\n            \"local_admin_password\": \"NgtI75cKV+Pu\",\n            \"domain\" : \"north.sevenkingdoms.local\",\n            \"path\" : \"DC=north,DC=sevenkingdoms,DC=local\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"north\\\\eddard.stark\",\n                    \"north\\\\catelyn.stark\",\n                    \"north\\\\robb.stark\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"north\\\\Stark\"\n                ]\n            },\n            \"scripts\" : [\n                \"asrep_roasting.ps1\",\n                \"constrained_delegation_use_any.ps1\",\n                \"constrained_delegation_kerb_only.ps1\",\n                \"ntlm_relay.ps1\",\n                \"responder.ps1\",\n                \"gpo_abuse.ps1\",\n                \"rdp_scheduler.ps1\"\n            ],\n            \"vulns\" : [\"disable_firewall\", \"directory\", \"credentials\", \"autologon\", \"files\", \"ntlmdowngrade\", \"enable_llmnr\", \"enable_nbt-ns\", \"shares\"],\n            \"vulns_vars\" : {\n                \"directory\": {\n                    \"setup\": \"c:\\\\setup\"\n                },\n                \"credentials\" : {\n                    \"TERMSRV/castelblack\": {\n                        \"username\" : \"north\\\\robb.stark\",\n                        \"secret\"   : \"sexywolfy\",\n                        \"runas\"    : \"north\\\\robb.stark\",\n                        \"runas_password\" : \"sexywolfy\"\n                    }\n                },\n                \"autologon\" : {\n                    \"robb.stark\" : {\n                        \"username\" : \"north\\\\robb.stark\",\n                        \"password\" : \"sexywolfy\"\n                    }\n                },\n                \"files\" : {\n                    \"rdp\" : {\n                        \"src\" : \"dc02/bot_rdp.ps1\",\n                        \"dest\" : \"c:\\\\setup\\\\bot_rdp.ps1\"\n                    },\n                    \"sysvol_fake_script\": {\n                        \"src\" : \"dc02/sysvol_scripts/script.ps1\",\n                        \"dest\": \"C:\\\\Windows\\\\SYSVOL\\\\domain\\\\scripts\\\\script.ps1\"\n                    },\n                    \"sysvol_secret\": {\n                        \"src\" : \"dc02/sysvol_scripts/secret.ps1\",\n                        \"dest\": \"C:\\\\Windows\\\\SYSVOL\\\\domain\\\\scripts\\\\secret.ps1\"\n                    }\n                }\n            }\n        },\n        \"srv02\" : {\n            \"hostname\" : \"castelblack\",\n            \"type\" : \"server\",\n            \"local_admin_password\": \"NgtI75cKV+Pu\",\n            \"domain\" : \"north.sevenkingdoms.local\",\n            \"path\" : \"DC=north,DC=sevenkingdoms,DC=local\",\n            \"use_laps\": false,\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"north\\\\jeor.mormont\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"north\\\\Night Watch\",\n                    \"north\\\\Mormont\",\n                    \"north\\\\Stark\"\n                ]\n            },\n            \"scripts\" : [],\n            \"vulns\" : [\"directory\", \"disable_firewall\", \"openshares\", \"files\", \"permissions\"],\n            \"vulns_vars\" : {\n                \"directory\": {\n                    \"shares\": \"C:\\\\shares\",\n                    \"all\": \"C:\\\\shares\\\\all\"\n                },\n                \"files\" : {\n                    \"website\" : {\n                        \"src\" : \"srv02/wwwroot\",\n                        \"dest\" : \"C:\\\\inetpub\\\\\"\n                    },\n                    \"letter_in_shares\": {\n                        \"src\" : \"srv02/all/arya.txt\",\n                        \"dest\": \"C:\\\\shares\\\\all\\\\arya.txt\"\n                    }\n                },\n                \"permissions\" : {\n                    \"IIS_IUSRS_upload\": {\n                        \"path\" : \"C:\\\\inetpub\\\\wwwroot\\\\upload\",\n                        \"user\" : \"IIS_IUSRS\",\n                        \"rights\" : \"FullControl\"\n                    }\n                }\n            },\n            \"mssql\":{\n                \"sa_password\": \"Sup1_sa_P@ssw0rd!\",\n                \"svcaccount\" : \"sql_svc\",\n                \"sysadmins\" : [\n                    \"NORTH\\\\jon.snow\"\n                ],\n                \"executeaslogin\" : {\n                    \"NORTH\\\\samwell.tarly\" : \"sa\",\n                    \"NORTH\\\\brandon.stark\" :  \"NORTH\\\\jon.snow\"\n                },\n                \"executeasuser\" : {\n                    \"arya_master_dbo\": {\n                        \"user\": \"NORTH\\\\arya.stark\",\n                        \"db\"  : \"master\",\n                        \"impersonate\" : \"dbo\"\n                    },\n                    \"arya_dbms_dbo\": {\n                        \"user\": \"NORTH\\\\arya.stark\",\n                        \"db\"  : \"msdb\",\n                        \"impersonate\" : \"dbo\"\n                    }\n                }\n            }\n        }\n    },\n    \"domains\" : {\n        \"north.sevenkingdoms.local\" : {\n            \"dc\": \"dc02\",\n            \"domain_password\" : \"NgtI75cKV+Pu\",\n            \"netbios_name\": \"NORTH\",\n            \"trust\" : \"\",\n            \"laps_path\": \"OU=Laps,DC=north,DC=sevenkingdoms,DC=local\",\n            \"organisation_units\" : {\n            },\n            \"groups\" : {\n                \"universal\" : {},\n                \"global\" : {\n                    \"Stark\" : {\n                        \"managed_by\" : \"eddard.stark\",\n                        \"path\" : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"Night Watch\" : {\n                        \"managed_by\" : \"jeor.mormont\",\n                        \"path\" : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"Mormont\" : {\n                        \"managed_by\" : \"jeor.mormont\",\n                        \"path\" : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                    }\n                },\n                \"domainlocal\" : {\n                    \"AcrossTheSea\" : {\n                        \"path\" : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                    }\n                }\n            },\n            \"multi_domain_groups_member\" : {},\n            \"acls\" : {\n                \"anonymous_rpc\" : {\"for\": \"NT AUTHORITY\\\\ANONYMOUS LOGON\", \"to\": \"DC=North,DC=sevenkingdoms,DC=local\", \"right\": \"ReadProperty\", \"inheritance\": \"All\"},\n                \"anonymous_rpc2\" : {\"for\": \"NT AUTHORITY\\\\ANONYMOUS LOGON\", \"to\": \"DC=North,DC=sevenkingdoms,DC=local\", \"right\": \"GenericExecute\", \"inheritance\": \"All\"}\n            },\n            \"users\" : {\n                \"arya.stark\" : {\n                    \"firstname\"   : \"Arya\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"Needle\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Arya Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"eddard.stark\" : {\n                    \"firstname\"   : \"Eddard\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"FightP3aceAndHonor!\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Eddard Stark\",\n                    \"groups\"      : [\"Stark\", \"Domain Admins\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"catelyn.stark\" : {\n                    \"firstname\"   : \"Catelyn\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"robbsansabradonaryarickon\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Catelyn Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"robb.stark\" : {\n                    \"firstname\"   : \"Robb\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"sexywolfy\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Robb Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"sansa.stark\" : {\n                    \"firstname\"   : \"Sansa\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"345ertdfg\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Sansa Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\",\n                    \"spns\"        : [\"HTTP/eyrie.north.sevenkingdoms.local\"]\n                },\n                \"brandon.stark\" : {\n                    \"firstname\"   : \"Brandon\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"iseedeadpeople\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Brandon Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"rickon.stark\" : {\n                    \"firstname\"   : \"Rickon\",\n                    \"surname\"     : \"Stark\",\n                    \"password\"    : \"Winter2022\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Rickon Stark\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"hodor\" : {\n                    \"firstname\"   : \"hodor\",\n                    \"surname\"     : \"hodor\",\n                    \"password\"    : \"hodor\",\n                    \"city\"        : \"Winterfell\",\n                    \"description\" : \"Brainless Giant\",\n                    \"groups\"      : [\"Stark\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"jon.snow\" : {\n                    \"firstname\"   : \"Jon\",\n                    \"surname\"     : \"Snow\",\n                    \"password\"    : \"iknownothing\",\n                    \"city\"        : \"Castel Black\",\n                    \"description\" : \"Jon Snow\",\n                    \"groups\"      : [\"Stark\", \"Night Watch\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\",\n                    \"spns\"        : [\"HTTP/thewall.north.sevenkingdoms.local\"]\n                },\n                \"samwell.tarly\" : {\n                    \"firstname\"   : \"Samwell\",\n                    \"surname\"     : \"Tarly\",\n                    \"password\"    : \"Heartsbane\",\n                    \"city\"        : \"Castel Black\",\n                    \"description\" : \"Samwell Tarly (Password : Heartsbane)\",\n                    \"groups\"      : [\"Night Watch\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"jeor.mormont\" : {\n                    \"firstname\"   : \"Jeor\",\n                    \"surname\"     : \"Mormont\",\n                    \"password\"    : \"_L0ngCl@w_\",\n                    \"city\"        : \"Castel Black\",\n                    \"description\" : \"Jeor Mormont\",\n                    \"groups\"      : [\"Night Watch\", \"Mormont\"],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                },\n                \"sql_svc\" : {\n                    \"firstname\"   : \"sql\",\n                    \"surname\"     : \"service\",\n                    \"password\"    : \"YouWillNotKerboroast1ngMeeeeee\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"sql service\",\n                    \"groups\"      : [],\n                    \"path\"        : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\",\n                    \"spns\"        : [\"MSSQLSvc/castelblack.north.sevenkingdoms.local:1433\",\"MSSQLSvc/castelblack.north.sevenkingdoms.local\"]\n                }\n            }\n        },\n        \"sevenkingdoms.local\" : {\n            \"dc\": \"dc01\",\n            \"domain_password\" : \"8dCT-DJjgScp\",\n            \"netbios_name\": \"SEVENKINGDOMS\",\n            \"trust\" : \"\",\n            \"laps_path\": \"OU=Laps,DC=sevenkingdoms,DC=local\",\n            \"organisation_units\" : {\n                \"Vale\"        : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"IronIslands\" : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Riverlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Crownlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Stormlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Westerlands\" : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Reach\"       : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Dorne\"       : { \"path\" : \"DC=sevenkingdoms,DC=local\"}\n            },\n            \"groups\" : {\n                \"universal\" : {},\n                \"global\" : {\n                    \"Lannister\" : {\n                        \"managed_by\" : \"tywin.lannister\",\n                        \"path\" : \"OU=Westerlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"Baratheon\" : {\n                        \"managed_by\" : \"robert.baratheon\",\n                        \"path\" : \"OU=Stormlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"Small Council\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"DragonStone\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"KingsGuard\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"DragonRider\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    }\n                },\n                \"domainlocal\" : {\n                    \"AcrossTheNarrowSea\" : {\n                        \"path\" : \"CN=Users,DC=sevenkingdoms,DC=local\"\n                    }\n                }\n            },\n            \"multi_domain_groups_member\" : {\n            },\n            \"acls\" : {\n                \"forcechangepassword_tywin_jaime\" : {\"for\": \"tywin.lannister\", \"to\": \"jaime.lannister\", \"right\": \"Ext-User-Force-Change-Password\", \"inheritance\": \"None\"},\n                \"GenericWrite_on_user_jaimie_joffrey\" : {\"for\": \"jaime.lannister\", \"to\": \"joffrey.baratheon\", \"right\": \"GenericWrite\", \"inheritance\": \"None\"},\n                \"Writedacl_joffrey_tyron\" : {\"for\": \"joffrey.baratheon\", \"to\": \"tyron.lannister\", \"right\": \"WriteDacl\", \"inheritance\": \"None\"},\n                \"self-self-membership-on-group_tyron_small_council\" : {\"for\": \"tyron.lannister\", \"to\": \"Small Council\", \"right\": \"Ext-Self-Self-Membership\", \"inheritance\": \"None\"},\n                \"addmember_smallcouncil_DragonStone\" : {\"for\": \"Small Council\", \"to\": \"DragonStone\", \"right\": \"Ext-Write-Self-Membership\", \"inheritance\": \"All\"},\n                \"write_owner_dragonstone_kingsguard\" : {\"for\": \"DragonStone\", \"to\": \"KingsGuard\", \"right\": \"WriteOwner\", \"inheritance\": \"None\"},\n                \"GenericAll_kingsguard_stanis\" : {\"for\": \"KingsGuard\", \"to\": \"stannis.baratheon\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_stanis_dc\" : {\"for\": \"stannis.baratheon\", \"to\": \"kingslanding$\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_group_acrrosdom_dc\" : {\"for\": \"AcrossTheNarrowSea\", \"to\": \"kingslanding$\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_varys_domadmin\" : {\"for\": \"lord.varys\", \"to\": \"Domain Admins\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_varys_domadmin_holder\" : {\"for\": \"lord.varys\", \"to\": \"CN=AdminSDHolder,CN=System,DC=sevenkingdoms,DC=local\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"WriteDACL_renly_Crownlands\" : {\"for\": \"renly.baratheon\", \"to\": \"OU=Crownlands,DC=sevenkingdoms,DC=local\", \"right\": \"WriteDacl\", \"inheritance\": \"None\"}\n            },\n            \"users\" : {\n                \"tywin.lannister\" : {\n                    \"firstname\"   : \"Tywin\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"powerkingftw135\",\n                    \"city\"        : \"Casterly Rock\",\n                    \"description\" : \"Tywin Lanister\",\n                    \"groups\"      : [\"Lannister\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"jaime.lannister\" : {\n                    \"firstname\"   : \"Jaime\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"cersei\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Jaime Lanister\",\n                    \"groups\"      : [\"Lannister\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"cersei.lannister\" : {\n                    \"firstname\"   : \"Cersei\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"il0vejaime\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Cersei Lanister\",\n                    \"groups\"      : [\"Lannister\",\"Baratheon\",\"Domain Admins\",\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"tyron.lannister\" : {\n                    \"firstname\"   : \"Tyron\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"Alc00L&S3x\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Tyron Lanister\",\n                    \"groups\"      : [\"Lannister\"],\n                    \"path\"        : \"OU=Westerlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"robert.baratheon\" : {\n                    \"firstname\"   : \"Robert\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"iamthekingoftheworld\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Robert Lanister\",\n                    \"groups\"      : [\"Baratheon\",\"Domain Admins\",\"Small Council\",\"Protected Users\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"joffrey.baratheon\" : {\n                    \"firstname\"   : \"Joffrey\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"1killerlion\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Joffrey Baratheon\",\n                    \"groups\"      : [\"Baratheon\",\"Lannister\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"renly.baratheon\" : {\n                    \"firstname\"   : \"Renly\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"lorastyrell\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Renly Baratheon\",\n                    \"groups\"      : [\"Baratheon\",\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"stannis.baratheon\" : {\n                    \"firstname\"   : \"Stannis\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"Drag0nst0ne\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Stannis Baratheon\",\n                    \"groups\"      : [\"Baratheon\",\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"petyer.baelish\" : {\n                    \"firstname\"   : \"Petyer\",\n                    \"surname\"     : \"Baelish\",\n                    \"password\"    : \"@littlefinger@\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Petyer Baelish\",\n                    \"groups\"      : [\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"lord.varys\" : {\n                    \"firstname\"   : \"Lord\",\n                    \"surname\"     : \"Varys\",\n                    \"password\"    : \"_W1sper_$\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Lord Varys\",\n                    \"groups\"      : [\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"maester.pycelle\" : {\n                    \"firstname\"   : \"Maester\",\n                    \"surname\"     : \"Pycelle\",\n                    \"password\"    : \"MaesterOfMaesters\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Maester Pycelle\",\n                    \"groups\"      : [\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                }\n            }\n        }\n    }\n}}"
  },
  {
    "path": "ad/GOAD-Light/data/inventory",
    "content": "[all:vars]\n; domain_name : folder inside ad/\ndomain_name=GOAD-Light\n; administrator user\nadmin_user=administrator\n\nforce_dns_server=no\ndns_server=x.x.x.x\n\n;dns server forwarder\ndns_server_forwarder=1.1.1.1\n\n; winrm connection (windows)\nansible_user=vagrant\nansible_password=vagrant\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n# ansible_winrm_transport=basic\n# ansible_port=5985\n\n; proxy settings (the lab need internet for some install, if you are behind a proxy you should set the proxy here)\nenable_http_proxy=no\nad_http_proxy=http://x.x.x.x:xxxx\nad_https_proxy=http://x.x.x.x:xxxx\n\n; LAB SCENARIO CONFIGURATION -----------------------------\n\n; computers inside domain (mandatory)\n; usage : build.yml, ad-relations.yml, ad-servers.yml, vulnerabilities.yml\n[domain]\ndc01\ndc02\nsrv02\n\n; domain controler (mandatory)\n; usage : ad-acl.yml, ad-data.yml, ad-relations.yml, laps.yml\n[dc]\ndc01\ndc02\n\n; domain server to enroll (mandatory if you want servers)\n; usage : ad-data.yml, ad-servers.yml, laps.yml\n[server]\nsrv02\n\n; workstation to enroll (mandatory if you want workstation)\n; usage : ad-servers.yml, laps.yml\n[workstation]\n\n; parent domain controler (mandatory)\n; usage : ad-servers.yml\n[parent_dc]\ndc01\n\n; child domain controler (need a fqdn child_name.parent_name)\n; usage : ad-servers.yml\n[child_dc]\ndc02\n\n; external trust, need domain trust entry in config (bidirectionnal)\n; usage : ad-trusts.yml\n[trust]\n;dc01\n\n; install adcs\n; usage : adcs.yml\n[adcs]\ndc01\n\n; install custom template (dc)\n; usage : adcs.yml\n[adcs_customtemplates]\n\n; install iis with default website asp upload on 80\n; usage : servers.yml\n[iis]\nsrv02\n\n; install mssql\n; usage : servers.yml\n[mssql]\nsrv02\n\n; install mssql gui\n; usage : servers.yml\n[mssql_ssms]\nsrv02\n\n; install webdav \n[webdav]\nsrv02\n\n; install elk\n; usage : elk.yml\n[elk_server]\n\n; add log agent for elk\n; usage : elk.yml\n[elk_log]\n\n[laps_dc]\n[laps_server]\n[laps_workstation]\n\n\n; allow computer update\n; usage : update.yml\n[update]\nsrv02\n\n; disable update\n; usage : update.yml\n[no_update]\ndc01\ndc02\n\n; allow defender\n; usage : security.yml\n[defender_on]\ndc01\ndc02\n\n; disable defender\n; usage : security.yml\n[defender_off]\nsrv02\n"
  },
  {
    "path": "ad/GOAD-Light/data/inventory_disable_vagrant",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=administrator@sevenkingdoms.local ansible_password=8dCT-DJjgScp\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02 ansible_user=administrator@north.sevenkingdoms.local ansible_password=NgtI75cKV+Pu\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02 ansible_user=administrator@north.sevenkingdoms.local ansible_password=NgtI75cKV+Pu\n\n[all:vars]\n; domain_name : folder inside ad/\ndomain_name=GOAD-Light\n\n; winrm connection (windows)\nansible_winrm_transport=ntlm\nansible_user=notused\nansible_password=notused\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n\n\n; LAB SCENARIO CONFIGURATION -----------------------------\n[domain]\ndc01\ndc02\nsrv02\n"
  },
  {
    "path": "ad/GOAD-Light/files/dc02/bot_rdp.ps1",
    "content": "# https://learn.microsoft.com/fr-fr/troubleshoot/windows-server/user-profiles-and-logon/turn-on-automatic-logon\nif(-not(query session robb.stark /server:castelblack)) {\n  #kill process if exist\n  Get-Process mstsc -IncludeUserName | Where {$_.UserName -eq \"NORTH\\robb.stark\"}|Stop-Process\n  #run the command\n  mstsc /v:castelblack\n}"
  },
  {
    "path": "ad/GOAD-Light/files/dc02/sysvol_scripts/script.ps1",
    "content": "# fake script in netlogon with creds\n$task = '/c TODO'\n$taskName = \"fake task\"\n$user = \"NORTH\\jeor.mormont\"\n$password = \"_L0ngCl@w_\"\n\n# passwords in sysvol still ..."
  },
  {
    "path": "ad/GOAD-Light/files/dc02/sysvol_scripts/secret.ps1",
    "content": "# cypher script\n# $domain=\"sevenkingdoms.local\"\n# $EncryptionKeyBytes = New-Object Byte[] 32\n# [Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($EncryptionKeyBytes)\n# $EncryptionKeyBytes | Out-File \"encryption.key\"\n# $EncryptionKeyData = Get-Content \"encryption.key\"\n# Read-Host -AsSecureString | ConvertFrom-SecureString -Key $EncryptionKeyData | Out-File -FilePath \"secret.encrypted\"\n\n# secret stored :\n$keyData = 177, 252, 228, 64, 28, 91, 12, 201, 20, 91, 21, 139, 255, 65, 9, 247, 41, 55, 164, 28, 75, 132, 143, 71, 62, 191, 211, 61, 154, 61, 216, 91\n$secret=\"76492d1116743f0423413b16050a5345MgB8AGkAcwBDACsAUwArADIAcABRAEcARABnAGYAMwA3AEEAcgBFAEIAYQB2AEEAPQA9AHwAZQAwADgANAA2ADQAMABiADYANAAwADYANgA1ADcANgAxAGIAMQBhAGQANQBlAGYAYQBiADQAYQA2ADkAZgBlAGQAMQAzADAANQAyADUAMgAyADYANAA3ADAAZABiAGEAOAA0AGUAOQBkAGMAZABmAGEANAAyADkAZgAyADIAMwA=\"\n\n# T.L."
  },
  {
    "path": "ad/GOAD-Light/files/srv02/all/arya.txt",
    "content": "Subject: Quick Departure\n\nHey Arya,\n\nI hope this message finds you well. Something urgent has come up, and I have to leave for a while. Don't worry; I'll be back soon.\n\nI left a little surprise for you in your room – the sword You've named \"Needle.\" It felt fitting, given your skills. Take care of it, and it'll take care of you.\n\nI'll explain everything when I return. Until then, stay sharp, sis.\n\nBest,\nJohn"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/Default.aspx",
    "content": "﻿<%@ Page Language=\"C#\" AutoEventWireup=\"true\" CodeBehind=\"Default.aspx.cs\" Inherits=\"WebApp.Default\" %>\r\n\r\n<!DOCTYPE html>\r\n\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n<head runat=\"server\">\r\n    <title></title>\r\n</head>\r\n<body>\r\n    File uploader to the upload/ folder\r\n    <form id=\"form1\" runat=\"server\">\r\n        <div>\r\n            <asp:FileUpload ID=\"FileUpload1\" runat=\"server\" /><br/>\r\n            <asp:Button ID=\"Button1\" runat=\"server\" Text=\"Upload File\" OnClick=\"UploadFile\" /><br/>\r\n            <asp:Label ID=\"Label1\" runat=\"server\" Text=\"\"></asp:Label>\r\n        </div>\r\n    </form>\r\n</body>\r\n</html>"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/Web.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!--\r\n  For more information on how to configure your ASP.NET application, please visit\r\n  https://go.microsoft.com/fwlink/?LinkId=169433\r\n  -->\r\n<configuration>\r\n  <system.web>\r\n    <compilation targetFramework=\"4.7.2\" />\r\n    <httpRuntime targetFramework=\"4.7.2\" />\r\n  </system.web>\r\n  <system.codedom>\r\n    <compilers>\r\n      <compiler language=\"c#;cs;csharp\" extension=\".cs\" type=\"Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" warningLevel=\"4\" compilerOptions=\"/langversion:default /nowarn:1659;1699;1701\" />\r\n      <compiler language=\"vb;vbs;visualbasic;vbscript\" extension=\".vb\" type=\"Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" warningLevel=\"4\" compilerOptions=\"/langversion:default /nowarn:41008 /define:_MYTYPE=\\&quot;Web\\&quot; /optionInfer+\" />\r\n    </compilers>\r\n  </system.codedom>\r\n</configuration>\r\n<!--ProjectGuid: 2B11A106-027E-4619-8BFC-1997E60A510C-->"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/bin/roslyn/Microsoft.CSharp.Core.targets",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <Import Project=\"Microsoft.Managed.Core.targets\"/>\r\n\r\n  <Target Name=\"CoreCompile\"\r\n          Inputs=\"$(MSBuildAllProjects);\r\n                  @(Compile);\r\n                  @(_CoreCompileResourceInputs);\r\n                  $(ApplicationIcon);\r\n                  $(AssemblyOriginatorKeyFile);\r\n                  @(ReferencePathWithRefAssemblies);\r\n                  @(CompiledLicenseFile);\r\n                  @(LinkResource);\r\n                  @(EmbeddedDocumentation);\r\n                  $(Win32Resource);\r\n                  $(Win32Manifest);\r\n                  @(CustomAdditionalCompileInputs);\r\n                  $(ResolvedCodeAnalysisRuleSet);\r\n                  @(AdditionalFiles);\r\n                  @(EmbeddedFiles)\"\r\n          Outputs=\"@(DocFileItem);\r\n                   @(IntermediateAssembly);\r\n                   @(IntermediateRefAssembly);\r\n                   @(_DebugSymbolsIntermediatePath);\r\n                   $(NonExistentFile);\r\n                   @(CustomAdditionalCompileOutputs)\"\r\n          Returns=\"@(CscCommandLineArgs)\"\r\n          DependsOnTargets=\"$(CoreCompileDependsOn);_BeforeVBCSCoreCompile\">\r\n    <!-- These two compiler warnings are raised when a reference is bound to a different version\r\n             than specified in the assembly reference version number.  MSBuild raises the same warning in this case,\r\n             so the compiler warning would be redundant. -->\r\n    <PropertyGroup Condition=\"('$(TargetFrameworkVersion)' != 'v1.0') and ('$(TargetFrameworkVersion)' != 'v1.1')\">\r\n      <NoWarn>$(NoWarn);1701;1702</NoWarn>\r\n    </PropertyGroup>\r\n\r\n    <PropertyGroup>\r\n      <!-- To match historical behavior, when inside VS11+ disable the warning from csc.exe indicating that no sources were passed in-->\r\n      <NoWarn Condition=\"'$(BuildingInsideVisualStudio)' == 'true' AND '$(VisualStudioVersion)' != '' AND '$(VisualStudioVersion)' &gt; '10.0'\">$(NoWarn);2008</NoWarn>\r\n    </PropertyGroup>\r\n\r\n    <PropertyGroup>\r\n      <!-- If the user has specified AppConfigForCompiler, we'll use it. If they have not, but they set UseAppConfigForCompiler,\r\n                 then we'll use AppConfig -->\r\n      <AppConfigForCompiler Condition=\"'$(AppConfigForCompiler)' == '' AND '$(UseAppConfigForCompiler)' == 'true'\">$(AppConfig)</AppConfigForCompiler>\r\n\r\n      <!-- If we are targeting winmdobj we want to specifically the pdbFile property since we do not want it to collide with the output of winmdexp-->\r\n      <PdbFile Condition=\"'$(PdbFile)' == '' AND '$(OutputType)' == 'winmdobj' AND '$(_DebugSymbolsProduced)' == 'true'\">$(IntermediateOutputPath)$(TargetName).compile.pdb</PdbFile>\r\n    </PropertyGroup>\r\n\r\n    <!-- Condition is to filter out the _CoreCompileResourceInputs so that it doesn't pass in culture resources to the compiler -->\r\n    <Csc Condition=\"'%(_CoreCompileResourceInputs.WithCulture)' != 'true'\"\r\n         AdditionalLibPaths=\"$(AdditionalLibPaths)\"\r\n         AddModules=\"@(AddModules)\"\r\n         AdditionalFiles=\"@(AdditionalFiles)\"\r\n         AllowUnsafeBlocks=\"$(AllowUnsafeBlocks)\"\r\n         Analyzers=\"@(Analyzer)\"\r\n         ApplicationConfiguration=\"$(AppConfigForCompiler)\"\r\n         BaseAddress=\"$(BaseAddress)\"\r\n         CheckForOverflowUnderflow=\"$(CheckForOverflowUnderflow)\"\r\n         ChecksumAlgorithm=\"$(ChecksumAlgorithm)\"\r\n         CodeAnalysisRuleSet=\"$(ResolvedCodeAnalysisRuleSet)\"\r\n         CodePage=\"$(CodePage)\"\r\n         DebugType=\"$(DebugType)\"\r\n         DefineConstants=\"$(DefineConstants)\"\r\n         DelaySign=\"$(DelaySign)\"\r\n         DisabledWarnings=\"$(NoWarn)\"\r\n         DocumentationFile=\"@(DocFileItem)\"\r\n         EmbedAllSources=\"$(EmbedAllSources)\"\r\n         EmbeddedFiles=\"@(EmbeddedFiles)\"\r\n         EmitDebugInformation=\"$(DebugSymbols)\"\r\n         EnvironmentVariables=\"$(CscEnvironment)\"\r\n         ErrorEndLocation=\"$(ErrorEndLocation)\"\r\n         ErrorLog=\"$(ErrorLog)\"\r\n         ErrorReport=\"$(ErrorReport)\"\r\n         Features=\"$(Features)\"\r\n         FileAlignment=\"$(FileAlignment)\"\r\n         GenerateFullPaths=\"$(GenerateFullPaths)\"\r\n         HighEntropyVA=\"$(HighEntropyVA)\"\r\n         Instrument=\"$(Instrument)\"\r\n         KeyContainer=\"$(KeyContainerName)\"\r\n         KeyFile=\"$(KeyOriginatorFile)\"\r\n         LangVersion=\"$(LangVersion)\"\r\n         LinkResources=\"@(LinkResource)\"\r\n         MainEntryPoint=\"$(StartupObject)\"\r\n         ModuleAssemblyName=\"$(ModuleAssemblyName)\"\r\n         NoConfig=\"true\"\r\n         NoLogo=\"$(NoLogo)\"\r\n         NoStandardLib=\"$(NoCompilerStandardLib)\"\r\n         NoWin32Manifest=\"$(NoWin32Manifest)\"\r\n         Optimize=\"$(Optimize)\"\r\n         Deterministic=\"$(Deterministic)\"\r\n         PublicSign=\"$(PublicSign)\"\r\n         OutputAssembly=\"@(IntermediateAssembly)\"\r\n         OutputRefAssembly=\"@(IntermediateRefAssembly)\"\r\n         PdbFile=\"$(PdbFile)\"\r\n         Platform=\"$(PlatformTarget)\"\r\n         Prefer32Bit=\"$(Prefer32Bit)\"\r\n         PreferredUILang=\"$(PreferredUILang)\"\r\n         ProvideCommandLineArgs=\"$(ProvideCommandLineArgs)\"\r\n         References=\"@(ReferencePathWithRefAssemblies)\"\r\n         ReportAnalyzer=\"$(ReportAnalyzer)\"\r\n         Resources=\"@(_CoreCompileResourceInputs);@(CompiledLicenseFile)\"\r\n         ResponseFiles=\"$(CompilerResponseFile)\"\r\n         RuntimeMetadataVersion=\"$(RuntimeMetadataVersion)\"\r\n         SharedCompilationId=\"$(SharedCompilationId)\"\r\n         SkipCompilerExecution=\"$(SkipCompilerExecution)\"\r\n         Sources=\"@(Compile)\"\r\n         SubsystemVersion=\"$(SubsystemVersion)\"\r\n         TargetType=\"$(OutputType)\"\r\n         ToolExe=\"$(CscToolExe)\"\r\n         ToolPath=\"$(CscToolPath)\"\r\n         TreatWarningsAsErrors=\"$(TreatWarningsAsErrors)\"\r\n         UseHostCompilerIfAvailable=\"$(UseHostCompilerIfAvailable)\"\r\n         UseSharedCompilation=\"$(UseSharedCompilation)\"\r\n         Utf8Output=\"$(Utf8Output)\"\r\n         VsSessionGuid=\"$(VsSessionGuid)\"\r\n         WarningLevel=\"$(WarningLevel)\"\r\n         WarningsAsErrors=\"$(WarningsAsErrors)\"\r\n         WarningsNotAsErrors=\"$(WarningsNotAsErrors)\"\r\n         Win32Icon=\"$(ApplicationIcon)\"\r\n         Win32Manifest=\"$(Win32Manifest)\"\r\n         Win32Resource=\"$(Win32Resource)\"\r\n         PathMap=\"$(PathMap)\"\r\n         SourceLink=\"$(SourceLink)\">\r\n      <Output TaskParameter=\"CommandLineArgs\" ItemName=\"CscCommandLineArgs\" />\r\n    </Csc>\r\n\r\n    <ItemGroup>\r\n      <_CoreCompileResourceInputs Remove=\"@(_CoreCompileResourceInputs)\" />\r\n    </ItemGroup>\r\n\r\n    <CallTarget Targets=\"$(TargetsTriggeredByCompilation)\" Condition=\"'$(TargetsTriggeredByCompilation)' != ''\" />\r\n  </Target>\r\n</Project>"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/bin/roslyn/Microsoft.Managed.Core.targets",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <!--\r\n    Common targets for managed compilers.\r\n  -->\r\n  <UsingTask TaskName=\"Microsoft.CodeAnalysis.BuildTasks.MapSourceRoots\" AssemblyFile=\"$(MSBuildThisFileDirectory)Microsoft.Build.Tasks.CodeAnalysis.dll\" />\r\n\r\n  <Target Name=\"ShimReferencePathsWhenCommonTargetsDoesNotUnderstandReferenceAssemblies\"\r\n          BeforeTargets=\"CoreCompile\"\r\n          Condition=\"'@(ReferencePathWithRefAssemblies)' == ''\">\r\n    <!-- \r\n      FindReferenceAssembliesForReferences target in Common targets populate this item \r\n      since dev15.3. The compiler targets may be used (via NuGet package) on earlier MSBuilds. \r\n      If the ReferencePathWithRefAssemblies item is not populated, just use ReferencePaths \r\n      (implementation assemblies) as they are.\r\n      \r\n      Since XAML inner build runs CoreCompile directly (instead of Compile target),\r\n      it also doesn't invoke FindReferenceAssembliesForReferences listed in CompileDependsOn.\r\n      In that case we also populate ReferencePathWithRefAssemblies with implementation assemblies.\r\n    -->\r\n    <ItemGroup>\r\n      <ReferencePathWithRefAssemblies Include=\"@(ReferencePath)\" />\r\n    </ItemGroup>\r\n  </Target>\r\n\r\n  <Target Name=\"_BeforeVBCSCoreCompile\"\r\n          DependsOnTargets=\"ShimReferencePathsWhenCommonTargetsDoesNotUnderstandReferenceAssemblies\">\r\n    \r\n    <ItemGroup Condition=\"'$(TargetingClr2Framework)' == 'true'\">\r\n      <ReferencePathWithRefAssemblies>\r\n        <EmbedInteropTypes />\r\n      </ReferencePathWithRefAssemblies>\r\n    </ItemGroup>\r\n\r\n    <!-- Prefer32Bit was introduced in .NET 4.5. Set it to false if we are targeting 4.0 -->\r\n    <PropertyGroup Condition=\"('$(TargetFrameworkVersion)' == 'v4.0')\">\r\n      <Prefer32Bit>false</Prefer32Bit>\r\n    </PropertyGroup>\r\n\r\n    <!-- TODO: Remove this ItemGroup once it has been moved to \"_GenerateCompileInputs\" target in Microsoft.Common.CurrentVersion.targets.\r\n         https://github.com/dotnet/roslyn/issues/12223 -->\r\n    <ItemGroup Condition=\"('$(AdditionalFileItemNames)' != '')\">\r\n      <AdditionalFileItems Include=\"$(AdditionalFileItemNames)\" />\r\n      <AdditionalFiles Include=\"@(%(AdditionalFileItems.Identity))\" />\r\n    </ItemGroup>\r\n\r\n    <PropertyGroup Condition=\"'$(UseSharedCompilation)' == ''\">\r\n      <UseSharedCompilation>true</UseSharedCompilation>\r\n    </PropertyGroup>\r\n  </Target>\r\n\r\n  <!--\r\n    ========================\r\n    DeterministicSourcePaths\r\n    ========================\r\n    \r\n    Unless specified otherwise enable deterministic source root (PathMap) when building deterministically on CI server, but not for local builds.\r\n    In order for the debugger to find source files when debugging a locally built binary the PDB must contain original, unmapped local paths.\r\n  -->\r\n  <PropertyGroup>\r\n    <DeterministicSourcePaths Condition=\"'$(DeterministicSourcePaths)' == '' and '$(Deterministic)' == 'true' and '$(ContinuousIntegrationBuild)' == 'true'\">true</DeterministicSourcePaths>\r\n  </PropertyGroup>\r\n\r\n  <!--\r\n    ==========\r\n    SourceRoot\r\n    ==========\r\n\r\n    All source files of the project are expected to be located under one of the directories specified by SourceRoot item group.\r\n    This target collects all SourceRoots from various sources.\r\n\r\n    This target calculates final local path for each SourceRoot and sets SourceRoot.MappedPath metadata accordingly.\r\n    The final path is a path with deterministic prefix when DeterministicSourcePaths is true, and the original path otherwise.\r\n    In addition, the target validates and deduplicates the SourceRoot items.\r\n\r\n    InitializeSourceControlInformation is an msbuild target that ensures the SourceRoot items are populated from source control.\r\n    The target is available only if SourceControlInformationFeatureSupported is true.\r\n\r\n    A consumer of SourceRoot.MappedPath metadata, such as Source Link generator, shall depend on this target. \r\n  -->\r\n\r\n  <Target Name=\"InitializeSourceRootMappedPaths\"\r\n          DependsOnTargets=\"_InitializeSourceRootMappedPathsFromSourceControl\">\r\n\r\n    <ItemGroup Condition=\"'@(_MappedSourceRoot)' != ''\">\r\n      <_MappedSourceRoot Remove=\"@(_MappedSourceRoot)\" />\r\n    </ItemGroup>\r\n\r\n    <Microsoft.CodeAnalysis.BuildTasks.MapSourceRoots SourceRoots=\"@(SourceRoot)\" Deterministic=\"$(DeterministicSourcePaths)\">\r\n      <Output TaskParameter=\"MappedSourceRoots\" ItemName=\"_MappedSourceRoot\" />\r\n    </Microsoft.CodeAnalysis.BuildTasks.MapSourceRoots>\r\n\r\n    <ItemGroup>\r\n      <SourceRoot Remove=\"@(SourceRoot)\" />\r\n      <SourceRoot Include=\"@(_MappedSourceRoot)\" />\r\n    </ItemGroup>\r\n  </Target>\r\n\r\n  <!-- \r\n    Declare that target InitializeSourceRootMappedPaths that populates MappedPaths metadata on SourceRoot items is available.\r\n  -->\r\n  <PropertyGroup>\r\n    <SourceRootMappedPathsFeatureSupported>true</SourceRootMappedPathsFeatureSupported>\r\n  </PropertyGroup>\r\n\r\n  <!-- \r\n    If InitializeSourceControlInformation target isn't supported, we just continue without invoking that synchronization target. \r\n    We'll proceed with SourceRoot (and other source control properties) provided by the user (or blank).\r\n  -->\r\n  <Target Name=\"_InitializeSourceRootMappedPathsFromSourceControl\"\r\n          DependsOnTargets=\"InitializeSourceControlInformation\"\r\n          Condition=\"'$(SourceControlInformationFeatureSupported)' == 'true'\" />\r\n\r\n  <!-- \r\n    =======\r\n    PathMap\r\n    =======\r\n\r\n    If DeterministicSourcePaths is true sets PathMap based on SourceRoot.MappedPaths.\r\n\r\n    This target requires SourceRoot to be initialized in order to calculate the PathMap.\r\n    If SourceRoot doesn't contain any top-level roots an error is reported.\r\n  -->\r\n\r\n  <Target Name=\"_SetPathMapFromSourceRoots\"\r\n          DependsOnTargets=\"InitializeSourceRootMappedPaths\"\r\n          BeforeTargets=\"CoreCompile\"\r\n          Condition=\"'$(DeterministicSourcePaths)' == 'true'\">\r\n\r\n    <ItemGroup>\r\n      <_TopLevelSourceRoot Include=\"@(SourceRoot)\" Condition=\"'%(SourceRoot.NestedRoot)' == ''\"/>\r\n    </ItemGroup>\r\n\r\n    <PropertyGroup Condition=\"'@(_TopLevelSourceRoot)' != ''\">\r\n      <!-- TODO: Report error/warning if /pathmap doesn't cover all emitted source paths: https://github.com/dotnet/roslyn/issues/23969 -->\r\n\r\n      <!-- TODO: PathMap should accept and ignore empty mapping: https://github.com/dotnet/roslyn/issues/23523 -->\r\n      <PathMap Condition=\"'$(PathMap)' != ''\">,$(PathMap)</PathMap>\r\n\r\n      <!--\r\n        Prepend the SourceRoot.MappedPath values to PathMap, if it already has a value.\r\n        For each emitted source path the compiler applies the first mapping that matches the path.\r\n        PathMap values set previously will thus only be applied if the mapping provided by \r\n        SourceRoot.MappedPath doesn't match. Since SourceRoot.MappedPath is also used by SourceLink \r\n        preferring it over manually set PathMap ensures that PathMap is consistent with SourceLink.\r\n      \r\n        TODO: quote the paths to avoid misinterpreting ',' and '=' in them as separators, \r\n        but quoting doesn't currently work (see https://github.com/dotnet/roslyn/issues/22835).\r\n      -->\r\n      <PathMap>@(_TopLevelSourceRoot->'%(Identity)=%(MappedPath)', ',')$(PathMap)</PathMap>\r\n    </PropertyGroup>\r\n  </Target>\r\n\r\n</Project>"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/bin/roslyn/Microsoft.VisualBasic.Core.targets",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <Import Project=\"Microsoft.Managed.Core.targets\"/>\r\n\r\n  <Target Name=\"CoreCompile\"\r\n          Inputs=\"$(MSBuildAllProjects);\r\n                  @(Compile);\r\n                  @(_CoreCompileResourceInputs);\r\n                  $(ApplicationIcon);\r\n                  $(AssemblyOriginatorKeyFile);\r\n                  @(ReferencePathWithRefAssemblies);\r\n                  @(CompiledLicenseFile);\r\n                  @(LinkResource);\r\n                  @(EmbeddedDocumentation);\r\n                  $(Win32Resource);\r\n                  $(Win32Manifest);\r\n                  @(CustomAdditionalCompileInputs);\r\n                  $(ResolvedCodeAnalysisRuleSet);\r\n                  @(AdditionalFiles);\r\n                  @(EmbeddedFiles)\"\r\n          Outputs=\"@(DocFileItem);\r\n                   @(IntermediateAssembly);\r\n                   @(IntermediateRefAssembly);\r\n                   @(_DebugSymbolsIntermediatePath);\r\n                   $(NonExistentFile);\r\n                   @(CustomAdditionalCompileOutputs)\"\r\n          Returns=\"@(VbcCommandLineArgs)\"\r\n          DependsOnTargets=\"$(CoreCompileDependsOn);_BeforeVBCSCoreCompile\">\r\n    <PropertyGroup>\r\n      <_NoWarnings Condition=\"'$(WarningLevel)' == '0'\">true</_NoWarnings>\r\n      <_NoWarnings Condition=\"'$(WarningLevel)' == '1'\">false</_NoWarnings>\r\n    </PropertyGroup>\r\n\r\n    <PropertyGroup>\r\n      <!-- If we are targeting winmdobj we want to specifically the pdbFile property since we do not want it to collide with the output of winmdexp-->\r\n      <PdbFile Condition=\"'$(PdbFile)' == '' AND '$(OutputType)' == 'winmdobj' AND '$(DebugSymbols)' == 'true'\">$(IntermediateOutputPath)$(TargetName).compile.pdb</PdbFile>\r\n    </PropertyGroup>\r\n\r\n    <!-- Condition is to filter out the _CoreCompileResourceInputs so that it doesn't pass in culture resources to the compiler -->\r\n    <Vbc Condition=\"'%(_CoreCompileResourceInputs.WithCulture)' != 'true'\"\r\n         AdditionalLibPaths=\"$(AdditionalLibPaths)\"\r\n         AddModules=\"@(AddModules)\"\r\n         AdditionalFiles=\"@(AdditionalFiles)\"\r\n         Analyzers=\"@(Analyzer)\"\r\n         BaseAddress=\"$(BaseAddress)\"\r\n         ChecksumAlgorithm=\"$(ChecksumAlgorithm)\"\r\n         CodeAnalysisRuleSet=\"$(ResolvedCodeAnalysisRuleSet)\"\r\n         CodePage=\"$(CodePage)\"\r\n         DebugType=\"$(DebugType)\"\r\n         DefineConstants=\"$(FinalDefineConstants)\"\r\n         DelaySign=\"$(DelaySign)\"\r\n         DisabledWarnings=\"$(NoWarn)\"\r\n         DocumentationFile=\"@(DocFileItem)\"\r\n         EmbedAllSources=\"$(EmbedAllSources)\"\r\n         EmbeddedFiles=\"@(EmbeddedFiles)\"\r\n         EmitDebugInformation=\"$(DebugSymbols)\"\r\n         EnvironmentVariables=\"$(VbcEnvironment)\"\r\n         ErrorLog=\"$(ErrorLog)\"\r\n         ErrorReport=\"$(ErrorReport)\"\r\n         Features=\"$(Features)\"\r\n         FileAlignment=\"$(FileAlignment)\"\r\n         GenerateDocumentation=\"$(GenerateDocumentation)\"\r\n         HighEntropyVA=\"$(HighEntropyVA)\"\r\n         Imports=\"@(Import)\"\r\n         Instrument=\"$(Instrument)\"\r\n         KeyContainer=\"$(KeyContainerName)\"\r\n         KeyFile=\"$(KeyOriginatorFile)\"\r\n         LangVersion=\"$(LangVersion)\"\r\n         LinkResources=\"@(LinkResource)\"\r\n         MainEntryPoint=\"$(StartupObject)\"\r\n         ModuleAssemblyName=\"$(ModuleAssemblyName)\"\r\n         NoConfig=\"true\"\r\n         NoStandardLib=\"$(NoCompilerStandardLib)\"\r\n         NoVBRuntimeReference=\"$(NoVBRuntimeReference)\"\r\n         NoWarnings=\"$(_NoWarnings)\"\r\n         NoWin32Manifest=\"$(NoWin32Manifest)\"\r\n         Optimize=\"$(Optimize)\"\r\n         Deterministic=\"$(Deterministic)\"\r\n         PublicSign=\"$(PublicSign)\"\r\n         OptionCompare=\"$(OptionCompare)\"\r\n         OptionExplicit=\"$(OptionExplicit)\"\r\n         OptionInfer=\"$(OptionInfer)\"\r\n         OptionStrict=\"$(OptionStrict)\"\r\n         OptionStrictType=\"$(OptionStrictType)\"\r\n         OutputAssembly=\"@(IntermediateAssembly)\"\r\n         OutputRefAssembly=\"@(IntermediateRefAssembly)\"\r\n         PdbFile=\"$(PdbFile)\"\r\n         Platform=\"$(PlatformTarget)\"\r\n         Prefer32Bit=\"$(Prefer32Bit)\"\r\n         PreferredUILang=\"$(PreferredUILang)\"\r\n         ProvideCommandLineArgs=\"$(ProvideCommandLineArgs)\"\r\n         References=\"@(ReferencePathWithRefAssemblies)\"\r\n         RemoveIntegerChecks=\"$(RemoveIntegerChecks)\"\r\n         ReportAnalyzer=\"$(ReportAnalyzer)\"\r\n         Resources=\"@(_CoreCompileResourceInputs);@(CompiledLicenseFile)\"\r\n         ResponseFiles=\"$(CompilerResponseFile)\"\r\n         RootNamespace=\"$(RootNamespace)\"\r\n         RuntimeMetadataVersion=\"$(RuntimeMetadataVersion)\"\r\n         SdkPath=\"$(FrameworkPathOverride)\"\r\n         SharedCompilationId=\"$(SharedCompilationId)\"\r\n         SkipCompilerExecution=\"$(SkipCompilerExecution)\"\r\n         Sources=\"@(Compile)\"\r\n         SubsystemVersion=\"$(SubsystemVersion)\"\r\n         TargetCompactFramework=\"$(TargetCompactFramework)\"\r\n         TargetType=\"$(OutputType)\"\r\n         ToolExe=\"$(VbcToolExe)\"\r\n         ToolPath=\"$(VbcToolPath)\"\r\n         TreatWarningsAsErrors=\"$(TreatWarningsAsErrors)\"\r\n         UseHostCompilerIfAvailable=\"$(UseHostCompilerIfAvailable)\"\r\n         UseSharedCompilation=\"$(UseSharedCompilation)\"\r\n         Utf8Output=\"$(Utf8Output)\"\r\n         VBRuntimePath=\"$(VBRuntimePath)\"\r\n         Verbosity=\"$(VbcVerbosity)\"\r\n         VsSessionGuid=\"$(VsSessionGuid)\"\r\n         WarningsAsErrors=\"$(WarningsAsErrors)\"\r\n         WarningsNotAsErrors=\"$(WarningsNotAsErrors)\"\r\n         Win32Icon=\"$(ApplicationIcon)\"\r\n         Win32Manifest=\"$(Win32Manifest)\"\r\n         Win32Resource=\"$(Win32Resource)\"\r\n         VBRuntime=\"$(VBRuntime)\"\r\n         PathMap=\"$(PathMap)\"\r\n         SourceLink=\"$(SourceLink)\">\r\n      <Output TaskParameter=\"CommandLineArgs\" ItemName=\"VbcCommandLineArgs\" />\r\n    </Vbc>\r\n    <ItemGroup>\r\n      <_CoreCompileResourceInputs Remove=\"@(_CoreCompileResourceInputs)\" />\r\n    </ItemGroup>\r\n\r\n    <CallTarget Targets=\"$(TargetsTriggeredByCompilation)\" Condition=\"'$(TargetsTriggeredByCompilation)' != ''\" />\r\n  </Target>\r\n</Project>"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/bin/roslyn/VBCSCompiler.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <gcServer enabled=\"true\" />\r\n    <gcConcurrent enabled=\"false\" />\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n  <appSettings>\r\n    <!-- Number of seconds with no activity before the server times out and closes. \r\n         Set to -1 to never shut down the server. -->\r\n    <add key=\"keepalive\" value=\"600\" />\r\n  </appSettings>\r\n</configuration>"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/bin/roslyn/csc.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <gcServer enabled=\"true\" />\r\n    <gcConcurrent enabled=\"false\" />\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n</configuration>"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/bin/roslyn/csc.rsp",
    "content": "﻿# Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.\r\n\r\n# This file contains command-line options that the C#\r\n# command line compiler (CSC) will process as part\r\n# of every compilation, unless the \"/noconfig\" option\r\n# is specified. \r\n\r\n# Reference the common Framework libraries\r\n/r:Accessibility.dll\r\n/r:Microsoft.CSharp.dll\r\n/r:System.Configuration.dll\r\n/r:System.Configuration.Install.dll\r\n/r:System.Core.dll\r\n/r:System.Data.dll\r\n/r:System.Data.DataSetExtensions.dll\r\n/r:System.Data.Linq.dll\r\n/r:System.Data.OracleClient.dll\r\n/r:System.Deployment.dll\r\n/r:System.Design.dll\r\n/r:System.DirectoryServices.dll\r\n/r:System.dll\r\n/r:System.Drawing.Design.dll\r\n/r:System.Drawing.dll\r\n/r:System.EnterpriseServices.dll\r\n/r:System.Management.dll\r\n/r:System.Messaging.dll\r\n/r:System.Runtime.Remoting.dll\r\n/r:System.Runtime.Serialization.dll\r\n/r:System.Runtime.Serialization.Formatters.Soap.dll\r\n/r:System.Security.dll\r\n/r:System.ServiceModel.dll\r\n/r:System.ServiceModel.Web.dll\r\n/r:System.ServiceProcess.dll\r\n/r:System.Transactions.dll\r\n/r:System.Web.dll\r\n/r:System.Web.Extensions.Design.dll\r\n/r:System.Web.Extensions.dll\r\n/r:System.Web.Mobile.dll\r\n/r:System.Web.RegularExpressions.dll\r\n/r:System.Web.Services.dll\r\n/r:System.Windows.Forms.dll\r\n/r:System.Workflow.Activities.dll\r\n/r:System.Workflow.ComponentModel.dll\r\n/r:System.Workflow.Runtime.dll\r\n/r:System.Xml.dll\r\n/r:System.Xml.Linq.dll\r\n"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/bin/roslyn/csi.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n</configuration>"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/bin/roslyn/csi.rsp",
    "content": "﻿/r:System\r\n/r:System.Core\r\n/r:Microsoft.CSharp\r\n/r:System.ValueTuple.dll\r\n/u:System\r\n/u:System.IO\r\n/u:System.Collections.Generic\r\n/u:System.Console\r\n/u:System.Diagnostics\r\n/u:System.Dynamic\r\n/u:System.Linq\r\n/u:System.Linq.Expressions\r\n/u:System.Text\r\n/u:System.Threading.Tasks"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/bin/roslyn/vbc.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <gcServer enabled=\"true\" />\r\n    <gcConcurrent enabled=\"false\" />\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n</configuration>"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/bin/roslyn/vbc.rsp",
    "content": "﻿# Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.\r\n\r\n# This file contains command-line options that the VB\r\n# command line compiler (VBC) will process as part\r\n# of every compilation, unless the \"/noconfig\" option\r\n# is specified. \r\n\r\n# Reference the common Framework libraries\r\n/r:Accessibility.dll\r\n/r:System.Configuration.dll\r\n/r:System.Configuration.Install.dll\r\n/r:System.Data.dll\r\n/r:System.Data.OracleClient.dll\r\n/r:System.Deployment.dll\r\n/r:System.Design.dll\r\n/r:System.DirectoryServices.dll\r\n/r:System.dll\r\n/r:System.Drawing.Design.dll\r\n/r:System.Drawing.dll\r\n/r:System.EnterpriseServices.dll\r\n/r:System.Management.dll\r\n/r:System.Messaging.dll\r\n/r:System.Runtime.Remoting.dll\r\n/r:System.Runtime.Serialization.Formatters.Soap.dll\r\n/r:System.Security.dll\r\n/r:System.ServiceProcess.dll\r\n/r:System.Transactions.dll\r\n/r:System.Web.dll\r\n/r:System.Web.Mobile.dll\r\n/r:System.Web.RegularExpressions.dll\r\n/r:System.Web.Services.dll\r\n/r:System.Windows.Forms.dll\r\n/r:System.XML.dll\r\n\r\n/r:System.Workflow.Activities.dll\r\n/r:System.Workflow.ComponentModel.dll\r\n/r:System.Workflow.Runtime.dll\r\n/r:System.Runtime.Serialization.dll\r\n/r:System.ServiceModel.dll\r\n\r\n/r:System.Core.dll\r\n/r:System.Xml.Linq.dll\r\n/r:System.Data.Linq.dll\r\n/r:System.Data.DataSetExtensions.dll\r\n/r:System.Web.Extensions.dll\r\n/r:System.Web.Extensions.Design.dll\r\n/r:System.ServiceModel.Web.dll\r\n\r\n# Import System and Microsoft.VisualBasic\r\n/imports:System\r\n/imports:Microsoft.VisualBasic\r\n/imports:System.Linq\r\n/imports:System.Xml.Linq\r\n\r\n/optioninfer+\r\n"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/index.html",
    "content": "<html>\n    <head>\n    </head>\n    <body>\n        <p>Please follow <a href=\"/Default.aspx\">this link</a> to upload your files.</p>\n    </body>\n</html>"
  },
  {
    "path": "ad/GOAD-Light/files/srv02/wwwroot/upload/.gitkeep",
    "content": ""
  },
  {
    "path": "ad/GOAD-Light/providers/aws/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=8dCT-DJjgScp\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02 ansible_user=ansible ansible_password=NgtI75cKV+Pu\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02 ansible_user=ansible ansible_password=NgtI75cKV+Pu\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/GOAD-Light/providers/aws/linux.tf",
    "content": "# \"lx01\" = {\n#   name               = \"lx01\"\n#   linux_sku          = \"22_04-lts-gen2\"\n#   linux_version      = \"latest\"\n#   ami                = \"ami-04c332520bd9cedb4\"\n#   private_ip_address = \"{{ip_range}}.40\"\n#   password           = \"suppaP@ssw0rd$\"\n#   size               = \"t2.medium\"\n# }"
  },
  {
    "path": "ad/GOAD-Light/providers/aws/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"dc01\"\n  domain             = \"sevenkingdoms.local\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCT-DJjgScp\"\n}\n\"dc02\" = {\n  name               = \"dc02\"\n  domain             = \"north.sevenkingdoms.local\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.11\"\n  password           = \"NgtI75cKV+Pu\"\n}\n\"srv02\" = {\n  name               = \"srv02\"\n  domain             = \"north.sevenkingdoms.local\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.22\"\n  password           = \"NgtI75cKV+Pu\"\n}"
  },
  {
    "path": "ad/GOAD-Light/providers/azure/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=8dCT-DJjgScp\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02 ansible_user=ansible ansible_password=NgtI75cKV+Pu\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02 ansible_user=ansible ansible_password=NgtI75cKV+Pu\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/GOAD-Light/providers/azure/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"dc01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\" # deprecated : \"2019.0.20181122\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCT-DJjgScp\"\n  size               = \"Standard_B2s\"\n}\n\"dc02\" = {\n  name               = \"dc02\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\" # deprecated : \"2019.0.20181122\"\n  private_ip_address = \"{{ip_range}}.11\"\n  password           = \"NgtI75cKV+Pu\"\n  size               = \"Standard_B2s\"\n}\n\"srv02\" = {\n  name               = \"srv02\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\" # deprecated : \"2019.0.20181122\"\n  private_ip_address = \"{{ip_range}}.22\"\n  password           = \"NgtI75cKV+Pu\"\n  size               = \"Standard_B2s\"\n}\n"
  },
  {
    "path": "ad/GOAD-Light/providers/ludus/config.yml",
    "content": "ludus:\n  - vm_name: \"{{ range_id }}-GOAD-DC01\"\n    hostname: \"{{ range_id }}-DC01\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 10\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-GOAD-DC02\"\n    hostname: \"{{ range_id }}-DC02\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 11\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-GOAD-SRV02\"\n    hostname: \"{{ range_id }}-SRV02\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 22\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n"
  },
  {
    "path": "ad/GOAD-Light/providers/ludus/inventory",
    "content": "[default]\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\n\n[all:vars]\nforce_dns_server=no\ndns_server={{ip_range}}.254\n\ndns_server_forwarder={{ip_range}}.254\n\nansible_user=localuser\nansible_password=password"
  },
  {
    "path": "ad/GOAD-Light/providers/proxmox/inventory",
    "content": "[default]\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\n\n[all:vars]\nforce_dns_server=yes\ndns_server={{ip_range}}.1"
  },
  {
    "path": "ad/GOAD-Light/providers/proxmox/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"DC01\"\n  desc               = \"DC01 - windows server 2019 - {{ip_range}}.10\"\n  cores              = 2\n  memory             = 3096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.10/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"dc02\" = {\n  name               = \"DC02\"\n  desc               = \"DC02 - windows server 2019 - {{ip_range}}.11\"\n  cores              = 2\n  memory             = 3096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.11/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"srv02\" = {\n  name               = \"SRV02\"\n  desc               = \"SRV02 - windows server 2019 - {{ip_range}}.22\"\n  cores              = 2\n  memory             = 6240\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.22/24\"\n  gateway            = \"{{ip_range}}.1\"\n}"
  },
  {
    "path": "ad/GOAD-Light/providers/virtualbox/Vagrantfile",
    "content": "boxes = [\n  # windows server 2019\n  { :name => \"GOAD-Light-DC01\",  :ip => \"{{ip_range}}.10\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-Light-DC02\",  :ip => \"{{ip_range}}.11\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-Light-SRV02\", :ip => \"{{ip_range}}.22\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 6000},\n]"
  },
  {
    "path": "ad/GOAD-Light/providers/virtualbox/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\n"
  },
  {
    "path": "ad/GOAD-Light/providers/vmware/Vagrantfile",
    "content": "boxes = [\n  # windows server 2019\n  { :name => \"GOAD-Light-DC01\",  :ip => \"{{ip_range}}.10\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-Light-DC02\",  :ip => \"{{ip_range}}.11\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-Light-SRV02\", :ip => \"{{ip_range}}.22\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 6000}\n]"
  },
  {
    "path": "ad/GOAD-Light/providers/vmware/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\n"
  },
  {
    "path": "ad/GOAD-Light/providers/vmware_esxi/Vagrantfile",
    "content": "boxes = [\n  # windows server 2019\n  { :name => \"GOAD-Light-DC01\",  :ip => \"{{ip_range}}.10\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-Light-DC02\",  :ip => \"{{ip_range}}.11\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  # windows server 2019\n  { :name => \"GOAD-Light-SRV02\", :ip => \"{{ip_range}}.22\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 6000}\n]"
  },
  {
    "path": "ad/GOAD-Light/providers/vmware_esxi/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n; ------------------------------------------------\n; north.sevenkingdoms.local\n; ------------------------------------------------\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=dc02\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\n"
  },
  {
    "path": "ad/GOAD-Light/scripts/archive/acl.ps1",
    "content": "# https://github.com/davidprowe/BadBlood/blob/master/AD_OU_SetACL/Full%20Control%20Permissions.ps1\nImport-Module ActiveDirectory\nSet-Location AD:\n\n###########################################################################################################\n# SetAcl  $for ---- $right ----> $to\n###########################################################################################################\nFunction SetAcl($for, $to, $right, $inheritance)\n{\n    $forSID = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser $for).SID\n    $objOU = ($to).DistinguishedName\n    $objAcl = get-acl $objOU\n    # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectoryrights?view=dotnet-plat-ext-5.0\n    $adRight =  [System.DirectoryServices.ActiveDirectoryRights] $right # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectoryrights?view=dotnet-plat-ext-5.0\n    $type =  [System.Security.AccessControl.AccessControlType] \"Allow\" # https://docs.microsoft.com/fr-fr/dotnet/api/system.security.accesscontrol.accesscontroltype?view=dotnet-plat-ext-5.0\n    $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] $inheritance # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectorysecurityinheritance?view=dotnet-plat-ext-5.0\n    $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $forSID,$adRight,$type,$inheritanceType\n    $objAcl.AddAccessRule($ace)\n    Set-Acl -AclObject $objAcl -path $objOU\n}\n\n# https://jorgequestforknowledge.wordpress.com/2014/08/20/powershell-and-dacls-in-ad-adding-ace-for-some-extended-right-on-some-object/\nFunction SetAclExtended($for, $to, $right, $extendedRightGUID, $inheritance)\n{\n    $forSID = New-Object System.Security.Principal.SecurityIdentifier (Get-ADUser $for).SID\n    $objOU = ($to).DistinguishedName\n    $objAcl = get-acl $objOU\n    # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectoryrights?view=dotnet-plat-ext-5.0\n    $adRight =  [System.DirectoryServices.ActiveDirectoryRights] $right # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectoryrights?view=dotnet-plat-ext-5.0\n    $type =  [System.Security.AccessControl.AccessControlType] \"Allow\" # https://docs.microsoft.com/fr-fr/dotnet/api/system.security.accesscontrol.accesscontroltype?view=dotnet-plat-ext-5.0\n    $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] $inheritance # https://docs.microsoft.com/fr-fr/dotnet/api/system.directoryservices.activedirectorysecurityinheritance?view=dotnet-plat-ext-5.0\n\n    $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $forSID,$adRight,$type,$extendedRightGUID,$inheritanceType\n    $objAcl.AddAccessRule($ace)\n    Set-Acl -AclObject $objAcl -path $objOU\n}\n\n## acl values :\n# AccessSystemSecurity\n# CreateChild\n# Delete\n# DeleteChild\n# DeleteTree\n# ExtendedRight\n# GenericAll\n# GenericExecute\n# GenericRead\n# GenericWrite\n# ListChildren\n# ListObject\n# ReadControl\n# ReadProperty\n# Self\n# Synchronize\n# WriteDacl\n# WriteOwner\n# WriteProperty \n\n## extend rights\n# \"00299570-246d-11d0-a768-00aa006e0529\" {$right = \"User-Force-Change-Password\"}\n# \"45ec5156-db7e-47bb-b53f-dbeb2d03c40\"  {$right = \"Reanimate-Tombstones\"}\n# \"bf9679c0-0de6-11d0-a285-00aa003049e2\" {$right = \"Self-Membership\"}\n# \"ba33815a-4f93-4c76-87f3-57574bff8109\" {$right = \"Manage-SID-History\"}\n# \"1131f6ad-9c07-11d1-f79f-00c04fc2dcd2\" {$right = \"DS-Replication-Get-Changes-All\"}\n\n# ACL abuse scenarios\n# https://sensepost.com/blog/2020/ace-to-rce/\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces\n# https://adsecurity.org/?p=3658\n\n# genericall-on-user\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#genericall-on-user\nSetAcl (Get-ADUser \"tywin.lannister\") (Get-ADUser \"cersei.lannister\") \"GenericAll\" \"None\"\n\n# genericall-on-group\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#genericall-on-group\nSetAcl (Get-ADUser \"lord.varys\") (Get-ADGroup \"Domain Admins\") \"GenericAll\" \"None\"\n\n# genericall-genericwrite-write-on-computer\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#genericall-genericwrite-write-on-computer\nSetAcl (Get-ADUser \"stannis.baratheon\") (Get-ADComputer \"kingslanding\") \"GenericAll\" \"None\"\n\n# writeproperty-on-group\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#writeproperty-on-group\nSetAcl (Get-ADUser \"petyer.baelish\") (Get-ADGroup \"Domain Admins\") \"WriteProperty\" \"All\"\n\n# self-self-membership-on-group\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#self-self-membership-on-group\nSetAclExtended (Get-ADUser \"tyron.lannister\") (Get-ADGroup \"Domain Admins\") \"Self\" \"bf9679c0-0de6-11d0-a285-00aa003049e2\" \"None\"\n\n# writeproperty-self-membership\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#writeproperty-self-membership\nSetAclExtended (Get-ADUser \"stannis.baratheon\") (Get-ADGroup \"Domain Admins\") \"WriteProperty\" \"bf9679c0-0de6-11d0-a285-00aa003049e2\" \"All\"\n\n# forcechangepassword\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#forcechangepassword\n# https://docs.microsoft.com/fr-fr/windows/win32/adschema/r-user-change-password\nSetAclExtended (Get-ADUser \"tywin.lannister\") (Get-ADUser \"jaime.lannister\") \"ExtendedRight\" \"00299570-246d-11d0-a768-00aa006e0529\" \"None\"\n\n# write owner on group\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#writeowner-on-group\nSetAcl (Get-ADUser \"maester.pycelle\") (Get-ADGroup \"Domain Admins\") \"WriteOwner\" \"None\"\n\n# genericwrite-on-user\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#genericwrite-on-user\nSetAcl (Get-ADUser \"jaime.lannister\") (Get-ADUser \"cersei.lannister\") \"GenericWrite\" \"None\"\n\n# writedacl-writeowner\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces#writedacl-writeowner\nSetAcl (Get-ADUser \"tywin.lannister\") (Get-ADGroup \"Small Council\") \"WriteDacl\" \"None\"\n"
  },
  {
    "path": "ad/GOAD-Light/scripts/archive/anonymous_ldap.ps1",
    "content": "$anonymousId = New-Object System.Security.Principal.NTAccount \"NT AUTHORITY\\ANONYMOUS LOGON\"\n$secInheritanceAll = [System.DirectoryServices.ActiveDirectorySecurityInheritance] \"All\"\n$Ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $anonymousId,\"ReadProperty, GenericExecute\",\"Allow\",$secInheritanceAll\n$Acl = Get-Acl -Path \"AD:$($node.DCPathEnd)\"\n$Acl.AddAccessRule($Ace)\nSet-Acl -Path \"AD:$($node.DCPathEnd)\" -AclObject $Acl"
  },
  {
    "path": "ad/GOAD-Light/scripts/archive/kerberoasting.ps1",
    "content": "Set-ADUser -Identity \"jon.snow\" -ServicePrincipalNames @{Add='HTTP/thewallserver'}"
  },
  {
    "path": "ad/GOAD-Light/scripts/archive/rbcd.ps1",
    "content": "# TODO"
  },
  {
    "path": "ad/GOAD-Light/scripts/archive/unconstrained_delegation.ps1",
    "content": "Get-ADComputer -Identity \"bravoos\" | Set-ADAccountControl -TrustedForDelegation $true"
  },
  {
    "path": "ad/GOAD-Light/scripts/asrep_roasting.ps1",
    "content": "Get-ADUser -Identity \"brandon.stark\" | Set-ADAccountControl -DoesNotRequirePreAuth:$true"
  },
  {
    "path": "ad/GOAD-Light/scripts/constrained_delegation_kerb_only.ps1",
    "content": "# https://www.thehacker.recipes/ad/movement/kerberos/delegations/constrained#without-protocol-transition\nSet-ADComputer -Identity \"castelblack$\" -ServicePrincipalNames @{Add='HTTP/winterfell.north.sevenkingdoms.local'}\nSet-ADComputer -Identity \"castelblack$\" -Add @{'msDS-AllowedToDelegateTo'=@('HTTP/winterfell.north.sevenkingdoms.local','HTTP/winterfell')}\n# Set-ADComputer -Identity \"castelblack$\" -Add @{'msDS-AllowedToDelegateTo'=@('CIFS/winterfell.north.sevenkingdoms.local','CIFS/winterfell')}"
  },
  {
    "path": "ad/GOAD-Light/scripts/constrained_delegation_use_any.ps1",
    "content": "# https://www.thehacker.recipes/ad/movement/kerberos/delegations/constrained#with-protocol-transition\nSet-ADUser -Identity \"jon.snow\" -ServicePrincipalNames @{Add='CIFS/winterfell.north.sevenkingdoms.local'}\nGet-ADUser -Identity \"jon.snow\" | Set-ADAccountControl -TrustedToAuthForDelegation $true\nSet-ADUser -Identity \"jon.snow\" -Add @{'msDS-AllowedToDelegateTo'=@('CIFS/winterfell.north.sevenkingdoms.local','CIFS/winterfell')}"
  },
  {
    "path": "ad/GOAD-Light/scripts/gpo_abuse.ps1",
    "content": "Install-WindowsFeature -Name GPMC\r\n$gpo_exist = Get-GPO -Name \"StarkWallpaper\" -erroraction ignore\r\n\r\nif ($gpo_exist) {\r\n    # Do nothing\r\n    #Remove-GPO -Name \"StarkWallpaper\"\r\n    #Remove the link of the GPO Remove-StarkWallpaper if it exists\r\n    #Remove-GPLink -Name \"StarkWallpaper\" -Target \"DC=north,DC=sevenkingdoms,DC=local\" -erroraction 'silentlycontinue'\r\n} else {\r\n    New-GPO -Name \"StarkWallpaper\" -comment \"Change Wallpaper\"\r\n    New-GPLink -Name \"StarkWallpaper\" -Target \"DC=north,DC=sevenkingdoms,DC=local\"\r\n\r\n    #https://www.thewindowsclub.com/set-desktop-wallpaper-using-group-policy-and-registry-editor\r\n    Set-GPRegistryValue -Name \"StarkWallpaper\" -key \"HKEY_CURRENT_USER\\Control Panel\\Colors\" -ValueName Background -Type String -Value \"100 175 200\"\r\n    #Set-GPPrefRegistryValue -Name \"StarkWallpaper\" -Context User -Action Create -Key \"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\" -ValueName Wallpaper -Type String -Value \"C:\\tmp\\GOAD.png\"\r\n\r\n    Set-GPRegistryValue -Name \"StarkWallpaper\" -key \"HKEY_CURRENT_USER\\Control Panel\\Desktop\" -ValueName Wallpaper -Type String -Value \"\"\r\n    #Set-GPPrefRegistryValue -Name \"StarkWallpaper\" -Context User -Action Create -Key \"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\" -ValueName WallpaperStyle -Type String -Value \"4\"\r\n\r\n    Set-GPRegistryValue -Name \"StarkWallpaper\" -Key \"HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon\" -ValueName SyncForegroundPolicy -Type DWORD -Value 1\r\n\r\n    # Allow samwell.tarly to Edit Settings of the GPO\r\n    # https://learn.microsoft.com/en-us/powershell/module/grouppolicy/set-gppermission?view=windowsserver2022-ps\r\n    Set-GPPermissions -Name \"StarkWallpaper\" -PermissionLevel GpoEditDeleteModifySecurity -TargetName \"samwell.tarly\" -TargetType \"User\"\r\n}"
  },
  {
    "path": "ad/GOAD-Light/scripts/ntlm_relay.ps1",
    "content": "$task = '/c powershell New-PSDrive -Name \"Public\" -PSProvider \"FileSystem\" -Root \"\\\\Meren\\Private\"'\n$repeat = (New-TimeSpan -Minutes 5)\n$taskName = \"ntlm_bot\"\n$user = \"north.sevenkingdoms.local\\eddard.stark\"\n$password = \"FightP3aceAndHonor!\"\n\n$action = New-ScheduledTaskAction -Execute \"cmd.exe\" -Argument \"$task\"\n$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat\n$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd\n\n$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName }\nif($taskExists) {\n    Unregister-ScheduledTask -TaskName $taskName -Confirm:$false\n}\nRegister-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings\n"
  },
  {
    "path": "ad/GOAD-Light/scripts/rdp_scheduler.ps1",
    "content": "$task = '/c powershell c:\\setup\\bot_rdp.ps1'\n$repeat = (New-TimeSpan -Minutes 1)\n$taskName = \"connect_bot\"\n$user = \"north\\robb.stark\"\n$password = \"sexywolfy\"\n$action = New-ScheduledTaskAction -Execute \"cmd.exe\" -Argument \"$task\"\n$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat\n$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd\n#$settings.CimInstanceProperties.Item('MultipleInstances').Value = 3   # 3 corresponds to 'Stop the existing instance'\n\n$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName }\nif($taskExists) {\n    Unregister-ScheduledTask -TaskName $taskName -Confirm:$false\n}\nRegister-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings"
  },
  {
    "path": "ad/GOAD-Light/scripts/responder.ps1",
    "content": "$task = '/c powershell New-PSDrive -Name \"Public\" -PSProvider \"FileSystem\" -Root \"\\\\Bravos\\private\"'\n$repeat = (New-TimeSpan -Minutes 2)\n$taskName = \"responder_bot\"\n$user = \"north.sevenkingdoms.local\\robb.stark\"\n$password = \"sexywolfy\"\n\n$action = New-ScheduledTaskAction -Execute \"cmd.exe\" -Argument \"$task\"\n$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat\n$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd\n\n$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName }\nif($taskExists) {\n    Unregister-ScheduledTask -TaskName $taskName -Confirm:$false\n}\nRegister-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings\n"
  },
  {
    "path": "ad/GOAD-Mini/README.md",
    "content": "# MINIGOAD\n\nMinimal lab with only sevenkingdoms.local domain and kingslanding DC, no more"
  },
  {
    "path": "ad/GOAD-Mini/data/config.json",
    "content": "{\n\"lab\" : {\n    \"hosts\" : {\n        \"dc01\" : {\n            \"hostname\" : \"kingslanding\",\n            \"type\" : \"dc\",\n            \"local_admin_password\": \"8dCT-DJjgScp\",\n            \"domain\" : \"sevenkingdoms.local\",\n            \"path\" : \"DC=sevenkingdoms,DC=local\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"sevenkingdoms\\\\robert.baratheon\",\n                    \"sevenkingdoms\\\\cersei.lannister\",\n                    \"sevenkingdoms\\\\DragonRider\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"sevenkingdoms\\\\Small Council\",\n                    \"sevenkingdoms\\\\Baratheon\"\n                ]\n            },\n            \"scripts\" : [],\n            \"vulns\" : [\"disable_firewall\", \"directory\", \"files\", \"adcs_templates\"],\n            \"vulns_vars\" : {\n                \"directory\": {\n                    \"setup\": \"c:\\\\setup\"\n                },\n                \"files\" : {\n                    \"template\" : {\n                        \"src\" : \"dc01/templates/\",\n                        \"dest\" : \"C:\\\\setup\\\\\"\n                    }\n                },\n                \"adcs_templates\": {\n                    \"ESC1\": {\n                        \"template_name\" : \"ESC1\",\n                        \"template_file\" : \"C:\\\\setup\\\\ESC1.json\"\n                    }\n                }\n            },\n            \"security\": [\"account_is_sensitive\"],\n            \"security_vars\": {\n                \"account_is_sensitive\" : { \"renly\": {\"account\" : \"renly.baratheon\"} }\n            }\n        }\n    },\n    \"domains\" : {\n        \"sevenkingdoms.local\" : {\n            \"dc\": \"dc01\",\n            \"domain_password\" : \"8dCT-DJjgScp\",\n            \"netbios_name\": \"SEVENKINGDOMS\",\n            \"trust\" : \"\",\n            \"laps_path\": \"OU=Laps,DC=sevenkingdoms,DC=local\",\n            \"organisation_units\" : {\n                \"Vale\"        : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"IronIslands\" : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Riverlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Crownlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Stormlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Westerlands\" : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Reach\"       : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Dorne\"       : { \"path\" : \"DC=sevenkingdoms,DC=local\"}\n            },\n            \"groups\" : {\n                \"universal\" : {},\n                \"global\" : {\n                    \"Lannister\" : {\n                        \"managed_by\" : \"tywin.lannister\",\n                        \"path\" : \"OU=Westerlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"Baratheon\" : {\n                        \"managed_by\" : \"robert.baratheon\",\n                        \"path\" : \"OU=Stormlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"Small Council\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"DragonStone\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"KingsGuard\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"DragonRider\" : {\n                        \"path\" : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                    }\n                },\n                \"domainlocal\" : {\n                    \"AcrossTheNarrowSea\" : {\n                        \"path\" : \"CN=Users,DC=sevenkingdoms,DC=local\"\n                    }\n                }\n            },\n            \"multi_domain_groups_member\" : {\n            },\n            \"acls\" : {\n                \"forcechangepassword_tywin_jaime\" : {\"for\": \"tywin.lannister\", \"to\": \"jaime.lannister\", \"right\": \"Ext-User-Force-Change-Password\", \"inheritance\": \"None\"},\n                \"GenericWrite_on_user_jaimie_joffrey\" : {\"for\": \"jaime.lannister\", \"to\": \"joffrey.baratheon\", \"right\": \"GenericWrite\", \"inheritance\": \"None\"},\n                \"Writedacl_joffrey_tyron\" : {\"for\": \"joffrey.baratheon\", \"to\": \"tyron.lannister\", \"right\": \"WriteDacl\", \"inheritance\": \"None\"},\n                \"self-self-membership-on-group_tyron_small_council\" : {\"for\": \"tyron.lannister\", \"to\": \"Small Council\", \"right\": \"Ext-Self-Self-Membership\", \"inheritance\": \"None\"},\n                \"addmember_smallcouncil_DragonStone\" : {\"for\": \"Small Council\", \"to\": \"DragonStone\", \"right\": \"Ext-Write-Self-Membership\", \"inheritance\": \"All\"},\n                \"write_owner_dragonstone_kingsguard\" : {\"for\": \"DragonStone\", \"to\": \"KingsGuard\", \"right\": \"WriteOwner\", \"inheritance\": \"None\"},\n                \"GenericAll_kingsguard_stanis\" : {\"for\": \"KingsGuard\", \"to\": \"stannis.baratheon\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_stanis_dc\" : {\"for\": \"stannis.baratheon\", \"to\": \"kingslanding$\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_group_acrrosdom_dc\" : {\"for\": \"AcrossTheNarrowSea\", \"to\": \"kingslanding$\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_varys_domadmin\" : {\"for\": \"lord.varys\", \"to\": \"Domain Admins\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_varys_domadmin_holder\" : {\"for\": \"lord.varys\", \"to\": \"CN=AdminSDHolder,CN=System,DC=sevenkingdoms,DC=local\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"WriteDACL_renly_Crownlands\" : {\"for\": \"renly.baratheon\", \"to\": \"OU=Crownlands,DC=sevenkingdoms,DC=local\", \"right\": \"WriteDacl\", \"inheritance\": \"None\"}\n            },\n            \"users\" : {\n                \"tywin.lannister\" : {\n                    \"firstname\"   : \"Tywin\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"powerkingftw135\",\n                    \"city\"        : \"Casterly Rock\",\n                    \"description\" : \"Tywin Lanister\",\n                    \"groups\"      : [\"Lannister\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"jaime.lannister\" : {\n                    \"firstname\"   : \"Jaime\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"cersei\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Jaime Lanister\",\n                    \"groups\"      : [\"Lannister\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"cersei.lannister\" : {\n                    \"firstname\"   : \"Cersei\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"il0vejaime\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Cersei Lanister\",\n                    \"groups\"      : [\"Lannister\",\"Baratheon\",\"Domain Admins\",\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"tyron.lannister\" : {\n                    \"firstname\"   : \"Tyron\",\n                    \"surname\"     : \"Lanister\",\n                    \"password\"    : \"Alc00L&S3x\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Tyron Lanister\",\n                    \"groups\"      : [\"Lannister\"],\n                    \"path\"        : \"OU=Westerlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"robert.baratheon\" : {\n                    \"firstname\"   : \"Robert\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"iamthekingoftheworld\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Robert Lanister\",\n                    \"groups\"      : [\"Baratheon\",\"Domain Admins\",\"Small Council\",\"Protected Users\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"joffrey.baratheon\" : {\n                    \"firstname\"   : \"Joffrey\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"1killerlion\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Joffrey Baratheon\",\n                    \"groups\"      : [\"Baratheon\",\"Lannister\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"renly.baratheon\" : {\n                    \"firstname\"   : \"Renly\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"lorastyrell\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Renly Baratheon\",\n                    \"groups\"      : [\"Baratheon\",\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"stannis.baratheon\" : {\n                    \"firstname\"   : \"Stannis\",\n                    \"surname\"     : \"Baratheon\",\n                    \"password\"    : \"Drag0nst0ne\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Stannis Baratheon\",\n                    \"groups\"      : [\"Baratheon\",\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"petyer.baelish\" : {\n                    \"firstname\"   : \"Petyer\",\n                    \"surname\"     : \"Baelish\",\n                    \"password\"    : \"@littlefinger@\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Petyer Baelish\",\n                    \"groups\"      : [\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"lord.varys\" : {\n                    \"firstname\"   : \"Lord\",\n                    \"surname\"     : \"Varys\",\n                    \"password\"    : \"_W1sper_$\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Lord Varys\",\n                    \"groups\"      : [\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                },\n                \"maester.pycelle\" : {\n                    \"firstname\"   : \"Maester\",\n                    \"surname\"     : \"Pycelle\",\n                    \"password\"    : \"MaesterOfMaesters\",\n                    \"city\"        : \"King's Landing\",\n                    \"description\" : \"Maester Pycelle\",\n                    \"groups\"      : [\"Small Council\"],\n                    \"path\"        : \"OU=Crownlands,DC=sevenkingdoms,DC=local\"\n                }\n            }\n        }\n    }\n}}"
  },
  {
    "path": "ad/GOAD-Mini/data/inventory",
    "content": "[all:vars]\n; domain_name : folder inside ad/\ndomain_name=GOAD-Mini\n; administrator user\nadmin_user=administrator\n\nforce_dns_server=no\ndns_server=x.x.x.x\n\n;dns server forwarder\ndns_server_forwarder=1.1.1.1\n\n; winrm connection (windows)\nansible_user=vagrant\nansible_password=vagrant\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n# ansible_winrm_transport=basic\n# ansible_port=5985\n\n; proxy settings (the lab need internet for some install, if you are behind a proxy you should set the proxy here)\nenable_http_proxy=no\nad_http_proxy=http://x.x.x.x:xxxx\nad_https_proxy=http://x.x.x.x:xxxx\n\n; LAB SCENARIO CONFIGURATION -----------------------------\n\n; computers inside domain (mandatory)\n; usage : build.yml, ad-relations.yml, ad-servers.yml, vulnerabilities.yml\n[domain]\ndc01\n\n; domain controler (mandatory)\n; usage : ad-acl.yml, ad-data.yml, ad-relations.yml, laps.yml\n[dc]\ndc01\n\n; domain server to enroll (mandatory if you want servers)\n; usage : ad-data.yml, ad-servers.yml, laps.yml\n[server]\n\n; workstation to enroll (mandatory if you want workstation)\n; usage : ad-servers.yml, laps.yml\n[workstation]\n\n; parent domain controler (mandatory)\n; usage : ad-servers.yml\n[parent_dc]\ndc01\n\n; child domain controler (need a fqdn child_name.parent_name)\n; usage : ad-servers.yml\n[child_dc]\n\n; external trust, need domain trust entry in config (bidirectionnal)\n; usage : ad-trusts.yml\n[trust]\n\n; install adcs\n; usage : adcs.yml\n[adcs]\ndc01\n\n; install custom template (dc)\n; usage : adcs.yml\n[adcs_customtemplates]\n\n; install iis with default website asp upload on 80\n; usage : servers.yml\n[iis]\n\n; install mssql\n; usage : servers.yml\n[mssql]\n\n; install mssql gui\n; usage : servers.yml\n[mssql_ssms]\n\n; install webdav \n[webdav]\n\n; install elk\n; usage : elk.yml\n[elk_server]\n\n; add log agent for elk\n; usage : elk.yml\n[elk_log]\n\n[laps_dc]\n[laps_server]\n[laps_workstation]\n\n\n; allow computer update\n; usage : update.yml\n[update]\n\n; disable update\n; usage : update.yml\n[no_update]\ndc01\n\n; allow defender\n; usage : security.yml\n[defender_on]\ndc01\n\n; disable defender\n; usage : security.yml\n[defender_off]\n"
  },
  {
    "path": "ad/GOAD-Mini/data/inventory_disable_vagrant",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=administrator@sevenkingdoms.local ansible_password=8dCT-DJjgScp\n\n[all:vars]\n; domain_name : folder inside ad/\ndomain_name=GOAD-Mini\n\n; winrm connection (windows)\nansible_winrm_transport=ntlm\nansible_user=notused\nansible_password=notused\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n\n\n; LAB SCENARIO CONFIGURATION -----------------------------\n[domain]\ndc01\n"
  },
  {
    "path": "ad/GOAD-Mini/providers/aws/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=8dCT-DJjgScp\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/GOAD-Mini/providers/aws/linux.tf",
    "content": "# \"lx01\" = {\n#   name               = \"lx01\"\n#   linux_sku          = \"22_04-lts-gen2\"\n#   linux_version      = \"latest\"\n#   ami                = \"ami-04c332520bd9cedb4\"\n#   private_ip_address = \"{{ip_range}}.40\"\n#   password           = \"suppaP@ssw0rd$\"\n#   size               = \"t2.medium\"\n# }"
  },
  {
    "path": "ad/GOAD-Mini/providers/aws/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"dc01\"\n  domain             = \"sevenkingdoms.local\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCT-DJjgScp\"\n}"
  },
  {
    "path": "ad/GOAD-Mini/providers/azure/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=8dCT-DJjgScp\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/GOAD-Mini/providers/azure/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"dc01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\" # deprecated : \"2019.0.20181122\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCT-DJjgScp\"\n  size               = \"Standard_B2s\"\n}\n"
  },
  {
    "path": "ad/GOAD-Mini/providers/ludus/config.yml",
    "content": "ludus:\n  - vm_name: \"{{ range_id }}-GOAD-DC01\"\n    hostname: \"{{ range_id }}-DC01\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 10\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n"
  },
  {
    "path": "ad/GOAD-Mini/providers/ludus/inventory",
    "content": "[default]\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n\n[all:vars]\nforce_dns_server=no\ndns_server={{ip_range}}.254\n\ndns_server_forwarder={{ip_range}}.254\n\nansible_user=localuser\nansible_password=password"
  },
  {
    "path": "ad/GOAD-Mini/providers/proxmox/inventory",
    "content": "[default]\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n\n[all:vars]\nforce_dns_server=yes\ndns_server={{ip_range}}.1"
  },
  {
    "path": "ad/GOAD-Mini/providers/proxmox/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"DC01\"\n  desc               = \"DC01 - windows server 2019 - {{ip_range}}.10\"\n  cores              = 2\n  memory             = 3096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.10/24\"\n  gateway            = \"{{ip_range}}.1\"\n}"
  },
  {
    "path": "ad/GOAD-Mini/providers/virtualbox/Vagrantfile",
    "content": "boxes = [\n  # windows server 2019\n  { :name => \"GOAD-Mini-DC01\",  :ip => \"{{ip_range}}.10\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000}\n]"
  },
  {
    "path": "ad/GOAD-Mini/providers/virtualbox/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n"
  },
  {
    "path": "ad/GOAD-Mini/providers/vmware/Vagrantfile",
    "content": "boxes = [\n  # windows server 2019\n  { :name => \"GOAD-Mini-DC01\",  :ip => \"{{ip_range}}.10\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000}\n]"
  },
  {
    "path": "ad/GOAD-Mini/providers/vmware/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n"
  },
  {
    "path": "ad/GOAD-Mini/providers/vmware_esxi/Vagrantfile",
    "content": "boxes = [\n  # windows server 2019\n  { :name => \"GOAD-Mini-DC01\",  :ip => \"{{ip_range}}.10\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\", :cpus => 2, :mem => 3000}\n]"
  },
  {
    "path": "ad/GOAD-Mini/providers/vmware_esxi/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sevenkingdoms.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\n"
  },
  {
    "path": "ad/NHA/README.md",
    "content": "# NINJA HACKER ACADEMY\n\n<div align=\"center\">\n<img src=\"./files/wwwroot/Content/logo.jpeg\" width=\"300px\"/>\n</div>\n\n- NINJA HACKER ACADEMY (NHA) is written as a training challenge where GOAD was written as a lab with a maximum of vulns.\n- You should find your way in to get domain admin on the 2 domains (academy.ninja.lan and ninja.hack)\n- Starting point is on srv01 : 192.168.58.21\n\n- Flags are disposed on each machine, try to grab all. Be careful all the machines are up to date with defender enabled.\n- Some exploits needs to modify path so this lab is not very multi-players compliant (unless you do it as a team ;))\n- Obviously do not cheat by looking at the passwords and flags in the recipe files, the lab must start without user to full compromise. \n\n- Install :\n\n```bash\n./goad.sh -t install -l NHA -p virtualbox -m docker\n```\n\n- Once install finish disable vagrant user to avoid using it :\n\n```bash\n./goad.sh -t disablevagrant -l NHA -p virtualbox -m docker\n```\n\n- Now do a reboot of all the machine to avoid unintended secrets stored : \n\n```bash\n./goad.sh -t stop -l NHA -p virtualbox -m docker\n./goad.sh -t start -l NHA -p virtualbox -m docker\n```\n\nAnd you are ready to play ! :)\n\n- If you need to re-enable vagrant\n\n```bash\n./goad.sh -t enablevagrant -l NHA -p virtualbox -m docker\n```\n\n- If you want to create a write up of the chall, no problem, have fun. Please ping me on X (@M4yFly) or Discord, i will be happy to read it :)\n\nHint: No bruteforce, if not in rockyou do not waste your time and your cpu/gpu cycle.\n"
  },
  {
    "path": "ad/NHA/data/config.json",
    "content": "{\n\"lab\" : {\n    \"hosts\" : {\n        \"dc01\" : {\n            \"hostname\" : \"dc-vil\",\n            \"type\" : \"dc\",\n            \"local_admin_password\": \"8dCT-6546541qsdDJjgScp\",\n            \"domain\" : \"ninja.hack\",\n            \"path\" : \"DC=ninja,DC=hack\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"ninja\\\\hokage\"\n                ]\n            },\n            \"vulns\" : [\"administrator_folder\",\"directory\",\"files\",\"adcs_templates\",\"acls\"],\n            \"vulns_vars\" : {\n                \"directory\": {\n                    \"setup\": \"c:\\\\setup\"\n                },\n                \"files\" : {\n                    \"template\" : {\n                        \"src\" : \"templates/SignatureValidation.json\",\n                        \"dest\" : \"C:\\\\setup\\\\SignatureValidation.json\"\n                    },\n                    \"flag\":{\n                        \"src\" : \"flags/dc_final.txt\",\n                        \"dest\": \"c:\\\\users\\\\administrator\\\\desktop\\\\flag.txt\"\n                    }\n                },\n                \"adcs_templates\": {\n                    \"SignatureValidation\": {\n                        \"template_name\" : \"SignatureValidation\",\n                        \"template_file\" : \"C:\\\\setup\\\\SignatureValidation.json\"\n                    }\n                },\n                \"acls\": {\n                    \"GenericAll_Jonin_signature\" : {\n                        \"for\": \"Jonin\", \n                        \"to\": \"CN=SignatureValidation,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=ninja,DC=hack\", \n                        \"right\": \"GenericAll\", \n                        \"inheritance\": \"None\"\n                    }\n                }\n            }\n        },\n        \"dc02\" : {\n            \"hostname\" : \"dc-ac\",\n            \"type\" : \"dc\",\n            \"local_admin_password\": \"Ufe-qsdaz789bVXSx9rk\",\n            \"domain\" : \"academy.ninja.lan\",\n            \"path\" : \"DC=academy,DC=ninja,DC=lan\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"academy\\\\Sensei\"\n                ]\n            },\n            \"scripts\" : [\n                \"constrained_delegation_use_any.ps1\"\n            ],\n            \"vulns\" : [\"administrator_folder\",\"files\"],\n            \"vulns_vars\" : {\n                \"files\" : {\n                    \"flag\":{\n                        \"src\" : \"flags/dc_academy.txt\",\n                        \"dest\": \"c:\\\\users\\\\administrator\\\\desktop\\\\flag.txt\"\n                    }\n                }\n            }\n        },\n        \"srv01\" : {\n            \"hostname\" : \"web\",\n            \"type\" : \"server\",\n            \"local_admin_password\": \"EaqsdP+xh7sdfzaRk6j90\",\n            \"domain\" : \"academy.ninja.lan\",\n            \"use_laps\": false,\n            \"path\" : \"DC=academy,DC=ninja,DC=lan\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"academy\\\\Sensei\",\n                    \"academy\\\\Teacher\"\n                ]\n            },\n            \"vulns\" : [\"administrator_folder\",\"files\", \"enable_credssp_server\"],\n            \"vulns_vars\" : {\n                \"files\" : {\n                    \"website\" : {\n                        \"src\" : \"wwwroot\",\n                        \"dest\" : \"C:\\\\inetpub\\\\\"\n                    },\n                    \"flag\":{\n                        \"src\" : \"flags/web.txt\",\n                        \"dest\": \"c:\\\\users\\\\administrator\\\\desktop\\\\flag.txt\"\n                    }\n                }\n            }\n        },\n        \"srv02\" : {\n            \"hostname\" : \"sql\",\n            \"type\" : \"server\",\n            \"local_admin_password\": \"978i2pF43UqsdqsdJ-qsd\",\n            \"domain\" : \"academy.ninja.lan\",\n            \"path\" : \"DC=academy,DC=ninja,DC=lan\",\n            \"use_laps\": false,\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"academy\\\\Sensei\",\n                    \"academy\\\\Teacher\"\n                ]\n            },\n            \"mssql\":{\n                \"sa_password\": \"sa_P@ssw0rd!N1nJ4hackaDemy\",\n                \"sysadmins\" : [\n                    \"academy\\\\frank\"\n                ],\n                \"executeaslogin\" : {},\n                \"executeasuser\" : {},\n                \"linked_servers\": {}\n            },\n            \"vulns\" : [\"administrator_folder\",\"files\", \"mssql\", \"disable_firewall\"],\n            \"vulns_vars\" : {\n                \"files\" : {\n                    \"sql\" : {\n                        \"src\" : \"SQL/academy_dump.sql\",\n                        \"dest\" : \"c:\\\\setup\\\\academy_dump.sql\"\n                    },\n                    \"flag_low\":{\n                        \"src\" : \"flags/sql_low.txt\",\n                        \"dest\": \"c:\\\\flag.txt\"\n                    },\n                    \"flag_high\":{\n                        \"src\" : \"flags/sql_high.txt\",\n                        \"dest\": \"c:\\\\users\\\\administrator\\\\desktop\\\\flag.txt\"\n                    }\n                },\n                \"mssql\": {\n                    \"init\" : {\n                        \"cmd\" : \"-i c:\\\\setup\\\\academy_dump.sql\"\n                    }\n                }\n            }\n        },\n        \"srv03\" : {\n            \"hostname\" : \"share\",\n            \"type\" : \"server\",\n            \"local_admin_password\": \"EalwxkfhqsdP+xh7sdfzaRk6j90\",\n            \"domain\" : \"academy.ninja.lan\",\n            \"use_laps\": false,\n            \"path\" : \"OU=share_servers,DC=academy,DC=ninja,DC=lan\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"academy\\\\Sensei\"\n                ]\n            },\n            \"vulns\" : [\"administrator_folder\",\"files\", \"enable_credssp_client\", \"schedule\"],\n            \"vulns_vars\" : {\n                \"files\" : {\n                    \"csp\" : {\n                        \"src\" : \"bot.ps1\",\n                        \"dest\" : \"c:\\\\bot.ps1\"\n                    },\n                    \"flag\":{\n                        \"src\" : \"flags/share.txt\",\n                        \"dest\": \"c:\\\\users\\\\administrator\\\\desktop\\\\flag.txt\"\n                    }\n                },\n                \"schedule\": {\n                    \"bot\": {\n                        \"name\": \"connect_bot\",\n                        \"cmd\" : \"powershell c:\\\\bot.ps1\",\n                        \"interval\" : \"PT1M\"\n                    }\n                }\n            }\n        }\n    },\n    \"domains\" : {\n        \"ninja.hack\" : {\n            \"dc\": \"dc01\",\n            \"domain_password\" : \"8dCT-6546541qsdDJjgScp\",\n            \"netbios_name\": \"NINJA\",\n            \"trust\" : \"academy.ninja.lan\",\n            \"ca_web_enrollment\": false,\n            \"organisation_units\" : {},\n            \"groups\" : {\n                \"universal\" : {},\n                \"global\" : {\n                    \"Jonin\" : {\n                        \"managed_by\" : \"david.wilson\",\n                        \"path\" : \"CN=Users,DC=ninja,DC=hack\"\n                    },\n                    \"Academy_Teacher\" : {\n                        \"managed_by\" : \"frank.umino\",\n                        \"path\" : \"CN=Users,DC=ninja,DC=hack\"\n                    },\n                    \"Hokage\" : {\n                        \"managed_by\" : \"alice.johnson\",\n                        \"path\" : \"CN=Users,DC=ninja,DC=hack\"\n                    }\n                },\n                \"domainlocal\" : {\n                    \"Sanin\" : {\n                        \"managed_by\" : \"rachel.philips\",\n                        \"path\" : \"CN=Users,DC=ninja,DC=hack\"\n                    }\n                }\n            },\n            \"multi_domain_groups_member\" : {},\n            \"acls\" : {\n                \"GenericAll_sanin_jonin\" : {\"for\": \"Sanin\", \"to\": \"Jonin\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"WriteDacl_olivia_rachel\" : {\"for\": \"olivia.davis\", \"to\": \"rachel.philips\", \"right\": \"WriteDacl\", \"inheritance\": \"None\"},\n                \"GenericAll_hokage_domadmin\" : {\"for\": \"hokage\", \"to\": \"Domain Admins\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"GenericAll_hokage_domadmin_holder\" : {\"for\": \"hokage\", \"to\": \"CN=AdminSDHolder,CN=System,DC=ninja,DC=hack\", \"right\": \"GenericAll\", \"inheritance\": \"None\"}\n            },\n            \"users\" : {\n                \"alice.johnson\" : {\n                    \"firstname\"   : \"Alice\",\n                    \"surname\"     : \"johnson\",\n                    \"password\"    : \"Ih@teC0mputeRs\", \n                    \"city\"        : \"ninja\",\n                    \"description\" : \"hokage\",\n                    \"groups\"      : [\"Hokage\", \"Domain Admins\"],\n                    \"path\"        : \"CN=Users,DC=ninja,DC=hack\"\n                },\n                \"david.wilson\" : {\n                    \"firstname\"   : \"david\",\n                    \"surname\"     : \"wilson\",\n                    \"password\"    : \"Sh@r1ngAnnFTW\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 7 captain\",\n                    \"groups\"      : [\"Jonin\"],\n                    \"path\"        : \"CN=Users,DC=ninja,DC=hack\"\n                },\n                \"yara.yuhi\" : {\n                    \"firstname\"   : \"yara\",\n                    \"surname\"     : \"yuhi\",\n                    \"password\"    : \"IgotR3dEy3s\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 8 captain\",\n                    \"groups\"      : [\"Jonin\"],\n                    \"path\"        : \"CN=Users,DC=ninja,DC=hack\"\n                },\n                \"katherine.white\" : {\n                    \"firstname\"   : \"katherine\",\n                    \"surname\"     : \"white\",\n                    \"password\"    : \"StrongOfTheYoung!!\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 9 captain\",\n                    \"groups\"      : [\"Jonin\"],\n                    \"path\"        : \"CN=Users,DC=ninja,DC=hack\"\n                },\n                \"uma.johnson\" : {\n                    \"firstname\"   : \"Uma\",\n                    \"surname\"     : \"Johnson\",\n                    \"password\"    : \"Il0veSmOOking\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 10 captain\",\n                    \"groups\"      : [\"Jonin\"],\n                    \"path\"        : \"CN=Users,DC=ninja,DC=hack\"\n                },\n                \"frank.umino\" : {\n                    \"firstname\"   : \"frank\",\n                    \"surname\"     : \"umino\",\n                    \"password\"    : \"Il0ve!R4men_\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Academy teacher\",\n                    \"groups\"      : [\"Academy_Teacher\"],\n                    \"path\"        : \"CN=Users,DC=ninja,DC=hack\"\n                },\n                \"olivia.davis\" : {\n                    \"firstname\"   : \"olivia\",\n                    \"surname\"     : \"davis\",\n                    \"password\"    : \"Il0veSexyJuTsu\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Academy teacher\",\n                    \"groups\"      : [\"Academy_Teacher\"],\n                    \"path\"        : \"CN=Users,DC=ninja,DC=hack\"\n                },\n                \"rachel.philips\" : {\n                    \"firstname\"   : \"Rachel\",\n                    \"surname\"     : \"Phillips\",\n                    \"password\"    : \"Il0ve_S4keee\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Sanin\",\n                    \"groups\"      : [\"Sanin\"],\n                    \"path\"        : \"CN=Users,DC=ninja,DC=hack\"\n                },\n                \"ava.brown\" : {\n                    \"firstname\"   : \"Ava\",\n                    \"surname\"     : \"Brown\",\n                    \"password\"    : \"Il0v3Pl@yingGamesss\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Sanin\",\n                    \"groups\"      : [\"Sanin\"],\n                    \"path\"        : \"CN=Users,DC=ninja,DC=hack\"\n                },\n                \"henry.martinez\" : {\n                    \"firstname\"   : \"Henry\",\n                    \"surname\"     : \"Martinez\",\n                    \"password\"    : \"Legend4_ryS4n1nFTW\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Sanin\",\n                    \"groups\"      : [\"Sanin\"],\n                    \"path\"        : \"CN=Users,DC=ninja,DC=hack\"\n                }\n            }\n        },\n        \"academy.ninja.lan\" : {\n            \"dc\": \"dc02\",\n            \"domain_password\" : \"Ufe-qsdaz789bVXSx9rk\",\n            \"netbios_name\": \"ACADEMY\",\n            \"trust\" : \"ninja.hack\",\n            \"organisation_units\" : {\n                \"share_servers\" : { \"path\" : \"DC=academy,DC=ninja,DC=lan\"}\n            },\n            \"groups\" : {\n                \"universal\" : {},\n                \"global\" : {\n                    \"Teacher\" : {\n                        \"managed_by\" : \"frank\",\n                        \"path\" : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                    },\n                    \"Sensei\" : {\n                        \"managed_by\" : \"alice\",\n                        \"path\" : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                    },\n                    \"Genin\" : {\n                        \"managed_by\" : \"frank\",\n                        \"path\" : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                    },\n                    \"Team7\" : {\n                        \"managed_by\" : \"david\",\n                        \"path\" : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                    },\n                    \"Team8\" : {\n                        \"managed_by\" : \"yara\",\n                        \"path\" : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                    },\n                    \"Team9\" : {\n                        \"managed_by\" : \"katherine\",\n                        \"path\" : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                    },\n                    \"Team10\" : {\n                        \"managed_by\" : \"uma\",\n                        \"path\" : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                    }\n                },\n                \"domainlocal\" : {}\n            },\n            \"multi_domain_groups_member\" : {},\n            \"gmsa\" : {\n                \"gmsa_nfs\": {\n                    \"gMSA_Name\" : \"gmsaNFS\",\n                    \"gMSA_FQDN\" : \"gmsaNFS.academy.ninja.lan\",\n                    \"gMSA_SPNs\" : [\"NFS/share\", \"NFS/share.academy.ninja.lan\"],\n                    \"gMSA_HostNames\" : [\"share\"]\n                }\n            },\n            \"acls\" : {\n                \"GenericAll_sql_computers\" : {\"for\": \"SQL$\", \"to\": \"CN=Computers,DC=academy,DC=ninja,DC=lan\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n                \"write_on_group_sensei\" : {\"for\": \"backup\", \"to\": \"Sensei\", \"right\": \"WriteOwner\", \"inheritance\": \"None\"},\n                \"write_on_group_domadmin_holder\" : {\"for\": \"backup\", \"to\": \"CN=AdminSDHolder,CN=System,DC=academy,DC=ninja,DC=lan\", \"right\": \"WriteOwner\", \"inheritance\": \"None\"},\n                \"forcechangepassword_gmsa_backup\" : {\"for\": \"gmsaNFS$\", \"to\": \"backup\", \"right\": \"Ext-User-Force-Change-Password\", \"inheritance\": \"None\"}\n            },\n            \"users\" : {\n                \"alice\" : {\n                    \"firstname\"   : \"alice\",\n                    \"surname\"     : \"johnson\",\n                    \"password\"    : \"C0mplexP@ssAD456\", \n                    \"city\"        : \"ninja\",\n                    \"description\" : \"hokage\",\n                    \"groups\"      : [\"Sensei\", \"Domain Admins\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"david\" : {\n                    \"firstname\"   : \"david\",\n                    \"surname\"     : \"wilson\",\n                    \"password\"    : \"MySh@r1ngCanSeeYuu\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 7 sensei\",\n                    \"groups\"      : [\"Sensei\", \"Team7\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"noah\" : {\n                    \"firstname\"   : \"Noah\",\n                    \"surname\"     : \"Young\",\n                    \"password\"    : \"ILoveRamen\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 7\",\n                    \"groups\"      : [\"Genin\", \"Team7\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"samuel\" : {\n                    \"firstname\"   : \"Samuel\",\n                    \"surname\"     : \"Evans\",\n                    \"password\"    : \"Ih@teAct1veDirectory\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 7\",\n                    \"groups\"      : [\"Genin\", \"Team7\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"willa\" : {\n                    \"firstname\"   : \"Willa\",\n                    \"surname\"     : \"Wilson\",\n                    \"password\"    : \"IL0veW3b\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 7\",\n                    \"groups\"      : [\"Genin\", \"Team7\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"yara\" : {\n                    \"firstname\"   : \"Yara\",\n                    \"surname\"     : \"Yuhi\",\n                    \"password\"    : \"IgotR3dEyes\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 8 sensei\",\n                    \"groups\"      : [\"Sensei\", \"Team8\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"zane\" : {\n                    \"firstname\"   : \"Zane\",\n                    \"surname\"     : \"Harris\",\n                    \"password\"    : \"IL0veRaclette\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 8\",\n                    \"groups\"      : [\"Genin\", \"Team8\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"ethan\" : {\n                    \"firstname\"   : \"Ethan\",\n                    \"surname\"     : \"Miller\",\n                    \"password\"    : \"InTartifletteWetrust\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 8\",\n                    \"groups\"      : [\"Genin\", \"Team8\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"scott\" : {\n                    \"firstname\"   : \"Scott\",\n                    \"surname\"     : \"Quinn\",\n                    \"password\"    : \"BugsBugsBugs\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 8\",\n                    \"groups\"      : [\"Genin\", \"Team8\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"katherine\" : {\n                    \"firstname\"   : \"Katherine\",\n                    \"surname\"     : \"White\",\n                    \"password\"    : \"TeamStrongOfTheYoung!!\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 9 sensei\",\n                    \"groups\"      : [\"Sensei\", \"Team9\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"victor\" : {\n                    \"firstname\"   : \"Victor\",\n                    \"surname\"     : \"Gonzalez\",\n                    \"password\"    : \"ByaKugaN!\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 9\",\n                    \"groups\"      : [\"Genin\", \"Team9\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"lee\" : {\n                    \"firstname\"   : \"Lee\",\n                    \"surname\"     : \"Liam\",\n                    \"password\"    : \"katherineSenseiIsTheBest\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 9\",\n                    \"groups\"      : [\"Genin\", \"Team9\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"taylor\" : {\n                    \"firstname\"   : \"Taylor\",\n                    \"surname\"     : \"Brown\",\n                    \"password\"    : \"KunaiAreMyBestFriends\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 9\",\n                    \"groups\"      : [\"Genin\", \"Team9\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"uma\" : {\n                    \"firstname\"   : \"Uma\",\n                    \"surname\"     : \"Johnson\",\n                    \"password\"    : \"SmOOkingL0v3\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 10 sensei\",\n                    \"groups\"      : [\"Sensei\", \"Team10\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"sophia\" : {\n                    \"firstname\"   : \"Sophia\",\n                    \"surname\"     : \"Taylor\",\n                    \"password\"    : \"PffBooring\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 10\",\n                    \"groups\"      : [\"Genin\", \"Team10\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"charlie\" : {\n                    \"firstname\"   : \"Charlie\",\n                    \"surname\"     : \"Davis\",\n                    \"password\"    : \"imnotBigOk\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 10\",\n                    \"groups\"      : [\"Genin\", \"Team10\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"isabella\" : {\n                    \"firstname\"   : \"Isabella\",\n                    \"surname\"     : \"Yamanaka\",\n                    \"password\"    : \"SophiaIsTooCute\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Team 10\",\n                    \"groups\"      : [\"Genin\", \"Team10\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"frank\" : {\n                    \"firstname\"   : \"frank\",\n                    \"surname\"     : \"umino\",\n                    \"password\"    : \"Il0ve!R4men_<3\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Academy teacher\",\n                    \"groups\"      : [\"Teacher\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\",\n                    \"spns\"        : [\"HTTP/WEB.academy.ninja.lan\"]\n                },\n                \"olivia\" : {\n                    \"firstname\"   : \"olivia\",\n                    \"surname\"     : \"davis\",\n                    \"password\"    : \"Il0veSexyJuTsu\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Academy teacher\",\n                    \"groups\"      : [\"Teacher\"],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"backup\" : {\n                    \"firstname\"   : \"backup\",\n                    \"surname\"     : \"user\",\n                    \"password\"    : \"N1nj4_b4ckup_U$er\",\n                    \"city\"        : \"ninja\",\n                    \"description\" : \"Backup Account\",\n                    \"groups\"      : [],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\"\n                },\n                \"sql_svc\" : {\n                    \"firstname\"   : \"sql\",\n                    \"surname\"     : \"service\",\n                    \"password\"    : \"MssqlD@tabase_On_lan\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"sql service\",\n                    \"groups\"      : [],\n                    \"path\"        : \"CN=Users,DC=academy,DC=ninja,DC=lan\",\n                    \"spns\"        : [\"MSSQLSvc/sql.academy.ninja.lan:1433\",\"MSSQLSvc/sql.academy.ninja.lan\"]\n                }\n            }\n        }\n    }\n}\n}"
  },
  {
    "path": "ad/NHA/data/inventory",
    "content": "[all:vars]\n; domain_name : folder inside ad/\ndomain_name=NHA\n; administrator user\nadmin_user=administrator\n\n;force_dns_server\nforce_dns_server=no\ndns_server=1.1.1.1\n\n;dns server forwarder\ndns_server_forwarder=1.1.1.1\n\n; winrm connection (windows)\nansible_user=vagrant\nansible_password=vagrant\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n\n; LAB SCENARIO CONFIGURATION -----------------------------\n\n; computers inside domain (mandatory)\n; usage : build.yml, ad-relations.yml, ad-servers.yml, vulnerabilities.yml\n[domain]\ndc01\ndc02\nsrv01\nsrv02\nsrv03\n\n; domain controler (mandatory)\n; usage : ad-acl.yml, ad-data.yml, ad-relations.yml, laps.yml\n[dc]\ndc01\ndc02\n\n; domain server to enroll (mandatory if you want servers)\n; usage : ad-data.yml, ad-servers.yml, laps.yml\n[server]\nsrv01\nsrv02\nsrv03\n\n; workstation to enroll (mandatory if you want workstation)\n; usage : ad-servers.yml, laps.yml\n[workstation]\n\n; parent domain controler (mandatory)\n; usage : ad-servers.yml\n[parent_dc]\ndc01\ndc02\n\n; child domain controler (need a fqdn child_name.parent_name)\n; usage : ad-servers.yml\n[child_dc]\n; external trust, need domain trust key in config (bidirectionnal)\n; usage : ad-trusts.yml\n[trust]\ndc01\ndc02\n\n; install adcs\n; usage : adcs.yml\n[adcs]\ndc01\n\n; install custom template (dc)\n; usage : adcs.yml\n[adcs_customtemplates]\n;dc01\n\n; install iis with default website asp upload on 80\n; usage : servers.yml\n[iis]\nsrv01\n\n; install mssql\n; usage : servers.yml\n[mssql]\nsrv02\n\n; install mssql gui\n; usage : servers.yml\n[mssql_ssms]\nsrv02\n\n; install webdav \n[webdav]\n; install elk\n; usage : elk.yml\n[elk_server]\n; add log agent for elk\n; usage : elk.yml\n[elk_log]\n\n[laps_dc]\n[laps_server]\n[laps_workstation]\n\n; allow computer update\n; usage : update.yml\n[update]\ndc01\ndc02\nsrv01\nsrv02\nsrv03\n\n; disable update\n; usage : update.yml\n[no_update]\n; allow defender (dc or server only)\n; usage : security.yml\n[defender_on]\ndc01\ndc02\nsrv01\nsrv02\nsrv03\n; disable defender (dc or server only)\n; usage : security.yml\n[defender_off]\n"
  },
  {
    "path": "ad/NHA/data/inventory_disable_vagrant",
    "content": "[default]\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=administrator@ninja.hack ansible_password=8dCT-6546541qsdDJjgScp\ndc02 ansible_host={{ip_range}}.20 dns_domain=dc02 dict_key=dc02 ansible_user=administrator@academy.ninja.lan ansible_password=Ufe-qsdaz789bVXSx9rk\nsrv01 ansible_host={{ip_range}}.21 dns_domain=dc02 dict_key=srv01 ansible_user=administrator@academy.ninja.lan ansible_password=Ufe-qsdaz789bVXSx9rk\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02 ansible_user=administrator@academy.ninja.lan ansible_password=Ufe-qsdaz789bVXSx9rk\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc02 dict_key=srv03 ansible_user=administrator@academy.ninja.lan ansible_password=Ufe-qsdaz789bVXSx9rk\n\n[all:vars]\n; domain_name : folder inside ad/\ndomain_name=NHA\n\n; winrm connection (windows)\nansible_winrm_transport=ntlm\nansible_user=notused\nansible_password=notused\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n\n[domain]\ndc01\ndc02\nsrv01\nsrv02\nsrv03\n"
  },
  {
    "path": "ad/NHA/files/bot.ps1",
    "content": "$pass=ConvertTo-SecureString 'Il0ve!R4men_<3' -AsPlainText -Force;\n$creds=New-Object System.Management.Automation.PSCredential ('academy.ninja.lan\\frank', $pass);\nInvoke-Command -Computername web.academy.ninja.lan -ScriptBlock {sleep 55} -Authentication 'Credssp' -Credential $creds"
  },
  {
    "path": "ad/NHA/files/flags/dc_academy.txt",
    "content": "NHA{WellD0ne_Sense1!_nowroot_secOnd_Domain}"
  },
  {
    "path": "ad/NHA/files/flags/dc_final.txt",
    "content": "NHA{CongraTul@T1ions_Young_HoKage!}"
  },
  {
    "path": "ad/NHA/files/flags/share.txt",
    "content": "NHA{Nice_DElegat1on_Dude!!}"
  },
  {
    "path": "ad/NHA/files/flags/sql_high.txt",
    "content": "NHA{OwwwYouTouchMyPatato!}"
  },
  {
    "path": "ad/NHA/files/flags/sql_low.txt",
    "content": "NHA{MSSQL_Inject1on_FTW;)}"
  },
  {
    "path": "ad/NHA/files/flags/web.txt",
    "content": "NHA{Computer_ContainerOOwnage!}"
  },
  {
    "path": "ad/NHA/files/wwwroot/Content/Site.css",
    "content": "﻿body {\r\n    padding-top: 50px;\r\n    padding-bottom: 20px;\r\n}\r\n\r\n/* Set padding to keep content from hitting the edges */\r\n.body-content {\r\n    padding-left: 15px;\r\n    padding-right: 15px;\r\n}\r\n\r\n/* Override the default bootstrap behavior where horizontal description lists \r\n   will truncate terms that are too long to fit in the left column \r\n*/\r\n.dl-horizontal dt {\r\n    white-space: normal;\r\n}\r\n\r\n/* Set width on the form input elements since they're 100% wide by default */\r\ninput,\r\nselect,\r\ntextarea {\r\n    max-width: 280px;\r\n}\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Content/bootstrap-theme.css",
    "content": "/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n  text-shadow: none;\n}\n.btn:active,\n.btn.active {\n  background-image: none;\n}\n.btn-default {\n  background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n  background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));\n  background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #dbdbdb;\n  text-shadow: 0 1px 0 #fff;\n  border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n  background-color: #e0e0e0;\n  background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n  background-color: #e0e0e0;\n  border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n  background-color: #e0e0e0;\n  background-image: none;\n}\n.btn-primary {\n  background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n  background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));\n  background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n  background-color: #265a88;\n  background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n  background-color: #265a88;\n  border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n  background-color: #265a88;\n  background-image: none;\n}\n.btn-success {\n  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n  background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));\n  background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n  background-color: #419641;\n  background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n  background-color: #419641;\n  border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n  background-color: #419641;\n  background-image: none;\n}\n.btn-info {\n  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n  background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));\n  background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n  background-color: #2aabd2;\n  background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n  background-color: #2aabd2;\n  border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n  background-color: #2aabd2;\n  background-image: none;\n}\n.btn-warning {\n  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n  background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));\n  background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n  background-color: #eb9316;\n  background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n  background-color: #eb9316;\n  border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n  background-color: #eb9316;\n  background-image: none;\n}\n.btn-danger {\n  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n  background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));\n  background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  background-repeat: repeat-x;\n  border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n  background-color: #c12e2a;\n  background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n  background-color: #c12e2a;\n  border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n  background-color: #c12e2a;\n  background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n  background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));\n  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n  background-repeat: repeat-x;\n  background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n  background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));\n  background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n  background-repeat: repeat-x;\n  background-color: #2e6da4;\n}\n.navbar-default {\n  background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n  background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#ffffff), to(#f8f8f8));\n  background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n  background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n  background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));\n  background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n  background-repeat: repeat-x;\n  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n  background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n  background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));\n  background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n  border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n  background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n  background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));\n  background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n  background-repeat: repeat-x;\n  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n  box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  border-radius: 0;\n}\n@media (max-width: 767px) {\n  .navbar .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #fff;\n    background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n    background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n    background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));\n    background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n    background-repeat: repeat-x;\n  }\n}\n.alert {\n  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n  background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));\n  background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #b2dba1;\n}\n.alert-info {\n  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n  background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));\n  background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #9acfea;\n}\n.alert-warning {\n  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n  background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));\n  background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #f5e79e;\n}\n.alert-danger {\n  background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n  background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));\n  background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #dca7a7;\n}\n.progress {\n  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n  background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));\n  background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n  background-repeat: repeat-x;\n}\n.progress-bar {\n  background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n  background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));\n  background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n  background-repeat: repeat-x;\n}\n.progress-bar-success {\n  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n  background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));\n  background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n  background-repeat: repeat-x;\n}\n.progress-bar-info {\n  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n  background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));\n  background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n  background-repeat: repeat-x;\n}\n.progress-bar-warning {\n  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n  background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));\n  background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n  background-repeat: repeat-x;\n}\n.progress-bar-danger {\n  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n  background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));\n  background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n  background-repeat: repeat-x;\n}\n.progress-bar-striped {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n  text-shadow: 0 -1px 0 #286090;\n  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n  background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));\n  background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n  text-shadow: none;\n}\n.panel {\n  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n  background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));\n  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n  background-repeat: repeat-x;\n}\n.panel-primary > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n  background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));\n  background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n  background-repeat: repeat-x;\n}\n.panel-success > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n  background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));\n  background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n  background-repeat: repeat-x;\n}\n.panel-info > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n  background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));\n  background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n  background-repeat: repeat-x;\n}\n.panel-warning > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n  background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));\n  background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n  background-repeat: repeat-x;\n}\n.panel-danger > .panel-heading {\n  background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n  background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));\n  background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n  background-repeat: repeat-x;\n}\n.well {\n  background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n  background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n  background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));\n  background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n  background-repeat: repeat-x;\n  border-color: #dcdcdc;\n  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */"
  },
  {
    "path": "ad/NHA/files/wwwroot/Content/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n  font-family: sans-serif;\n  -ms-text-size-adjust: 100%;\n  -webkit-text-size-adjust: 100%;\n}\nbody {\n  margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n  display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n  display: inline-block;\n  vertical-align: baseline;\n}\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n[hidden],\ntemplate {\n  display: none;\n}\na {\n  background-color: transparent;\n}\na:active,\na:hover {\n  outline: 0;\n}\nabbr[title] {\n  border-bottom: none;\n  text-decoration: underline;\n  -webkit-text-decoration: underline dotted;\n  -moz-text-decoration: underline dotted;\n  text-decoration: underline dotted;\n}\nb,\nstrong {\n  font-weight: bold;\n}\ndfn {\n  font-style: italic;\n}\nh1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\nmark {\n  background: #ff0;\n  color: #000;\n}\nsmall {\n  font-size: 80%;\n}\nsub,\nsup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\nsup {\n  top: -0.5em;\n}\nsub {\n  bottom: -0.25em;\n}\nimg {\n  border: 0;\n}\nsvg:not(:root) {\n  overflow: hidden;\n}\nfigure {\n  margin: 1em 40px;\n}\nhr {\n  -webkit-box-sizing: content-box;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\npre {\n  overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n  color: inherit;\n  font: inherit;\n  margin: 0;\n}\nbutton {\n  overflow: visible;\n}\nbutton,\nselect {\n  text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  -webkit-appearance: button;\n  cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  border: 0;\n  padding: 0;\n}\ninput {\n  line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n  height: auto;\n}\ninput[type=\"search\"] {\n  -webkit-appearance: textfield;\n  -webkit-box-sizing: content-box;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\nfieldset {\n  border: 1px solid #c0c0c0;\n  margin: 0 2px;\n  padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n  border: 0;\n  padding: 0;\n}\ntextarea {\n  overflow: auto;\n}\noptgroup {\n  font-weight: bold;\n}\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\ntd,\nth {\n  padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n  *,\n  *:before,\n  *:after {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    -webkit-box-shadow: none !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  a[href^=\"#\"]:after,\n  a[href^=\"javascript:\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n  .navbar {\n    display: none;\n  }\n  .btn > .caret,\n  .dropup > .btn > .caret {\n    border-top-color: #000 !important;\n  }\n  .label {\n    border: 1px solid #000;\n  }\n  .table {\n    border-collapse: collapse !important;\n  }\n  .table td,\n  .table th {\n    background-color: #fff !important;\n  }\n  .table-bordered th,\n  .table-bordered td {\n    border: 1px solid #ddd !important;\n  }\n}\n@font-face {\n  font-family: \"Glyphicons Halflings\";\n  src: url(\"../fonts/glyphicons-halflings-regular.eot\");\n  src: url(\"../fonts/glyphicons-halflings-regular.eot?#iefix\") format(\"embedded-opentype\"), url(\"../fonts/glyphicons-halflings-regular.woff2\") format(\"woff2\"), url(\"../fonts/glyphicons-halflings-regular.woff\") format(\"woff\"), url(\"../fonts/glyphicons-halflings-regular.ttf\") format(\"truetype\"), url(\"../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular\") format(\"svg\");\n}\n.glyphicon {\n  position: relative;\n  top: 1px;\n  display: inline-block;\n  font-family: \"Glyphicons Halflings\";\n  font-style: normal;\n  font-weight: 400;\n  line-height: 1;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n  content: \"\\002a\";\n}\n.glyphicon-plus:before {\n  content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n  content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n  content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n  content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n  content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n  content: \"\\270f\";\n}\n.glyphicon-glass:before {\n  content: \"\\e001\";\n}\n.glyphicon-music:before {\n  content: \"\\e002\";\n}\n.glyphicon-search:before {\n  content: \"\\e003\";\n}\n.glyphicon-heart:before {\n  content: \"\\e005\";\n}\n.glyphicon-star:before {\n  content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n  content: \"\\e007\";\n}\n.glyphicon-user:before {\n  content: \"\\e008\";\n}\n.glyphicon-film:before {\n  content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n  content: \"\\e010\";\n}\n.glyphicon-th:before {\n  content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n  content: \"\\e012\";\n}\n.glyphicon-ok:before {\n  content: \"\\e013\";\n}\n.glyphicon-remove:before {\n  content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n  content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n  content: \"\\e016\";\n}\n.glyphicon-off:before {\n  content: \"\\e017\";\n}\n.glyphicon-signal:before {\n  content: \"\\e018\";\n}\n.glyphicon-cog:before {\n  content: \"\\e019\";\n}\n.glyphicon-trash:before {\n  content: \"\\e020\";\n}\n.glyphicon-home:before {\n  content: \"\\e021\";\n}\n.glyphicon-file:before {\n  content: \"\\e022\";\n}\n.glyphicon-time:before {\n  content: \"\\e023\";\n}\n.glyphicon-road:before {\n  content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n  content: \"\\e025\";\n}\n.glyphicon-download:before {\n  content: \"\\e026\";\n}\n.glyphicon-upload:before {\n  content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n  content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n  content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n  content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n  content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n  content: \"\\e032\";\n}\n.glyphicon-lock:before {\n  content: \"\\e033\";\n}\n.glyphicon-flag:before {\n  content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n  content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n  content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n  content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n  content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n  content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n  content: \"\\e040\";\n}\n.glyphicon-tag:before {\n  content: \"\\e041\";\n}\n.glyphicon-tags:before {\n  content: \"\\e042\";\n}\n.glyphicon-book:before {\n  content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n  content: \"\\e044\";\n}\n.glyphicon-print:before {\n  content: \"\\e045\";\n}\n.glyphicon-camera:before {\n  content: \"\\e046\";\n}\n.glyphicon-font:before {\n  content: \"\\e047\";\n}\n.glyphicon-bold:before {\n  content: \"\\e048\";\n}\n.glyphicon-italic:before {\n  content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n  content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n  content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n  content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n  content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n  content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n  content: \"\\e055\";\n}\n.glyphicon-list:before {\n  content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n  content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n  content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n  content: \"\\e059\";\n}\n.glyphicon-picture:before {\n  content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n  content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n  content: \"\\e063\";\n}\n.glyphicon-tint:before {\n  content: \"\\e064\";\n}\n.glyphicon-edit:before {\n  content: \"\\e065\";\n}\n.glyphicon-share:before {\n  content: \"\\e066\";\n}\n.glyphicon-check:before {\n  content: \"\\e067\";\n}\n.glyphicon-move:before {\n  content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n  content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n  content: \"\\e070\";\n}\n.glyphicon-backward:before {\n  content: \"\\e071\";\n}\n.glyphicon-play:before {\n  content: \"\\e072\";\n}\n.glyphicon-pause:before {\n  content: \"\\e073\";\n}\n.glyphicon-stop:before {\n  content: \"\\e074\";\n}\n.glyphicon-forward:before {\n  content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n  content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n  content: \"\\e077\";\n}\n.glyphicon-eject:before {\n  content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n  content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n  content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n  content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n  content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n  content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n  content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n  content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n  content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n  content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n  content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n  content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n  content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n  content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n  content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n  content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n  content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n  content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n  content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n  content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n  content: \"\\e101\";\n}\n.glyphicon-gift:before {\n  content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n  content: \"\\e103\";\n}\n.glyphicon-fire:before {\n  content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n  content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n  content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n  content: \"\\e107\";\n}\n.glyphicon-plane:before {\n  content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n  content: \"\\e109\";\n}\n.glyphicon-random:before {\n  content: \"\\e110\";\n}\n.glyphicon-comment:before {\n  content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n  content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n  content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n  content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n  content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n  content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n  content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n  content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n  content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n  content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n  content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n  content: \"\\e122\";\n}\n.glyphicon-bell:before {\n  content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n  content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n  content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n  content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n  content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n  content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n  content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n  content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n  content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n  content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n  content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n  content: \"\\e134\";\n}\n.glyphicon-globe:before {\n  content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n  content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n  content: \"\\e137\";\n}\n.glyphicon-filter:before {\n  content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n  content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n  content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n  content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n  content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n  content: \"\\e143\";\n}\n.glyphicon-link:before {\n  content: \"\\e144\";\n}\n.glyphicon-phone:before {\n  content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n  content: \"\\e146\";\n}\n.glyphicon-usd:before {\n  content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n  content: \"\\e149\";\n}\n.glyphicon-sort:before {\n  content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n  content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n  content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n  content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n  content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n  content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n  content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n  content: \"\\e157\";\n}\n.glyphicon-expand:before {\n  content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n  content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n  content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n  content: \"\\e161\";\n}\n.glyphicon-flash:before {\n  content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n  content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n  content: \"\\e164\";\n}\n.glyphicon-record:before {\n  content: \"\\e165\";\n}\n.glyphicon-save:before {\n  content: \"\\e166\";\n}\n.glyphicon-open:before {\n  content: \"\\e167\";\n}\n.glyphicon-saved:before {\n  content: \"\\e168\";\n}\n.glyphicon-import:before {\n  content: \"\\e169\";\n}\n.glyphicon-export:before {\n  content: \"\\e170\";\n}\n.glyphicon-send:before {\n  content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n  content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n  content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n  content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n  content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n  content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n  content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n  content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n  content: \"\\e179\";\n}\n.glyphicon-header:before {\n  content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n  content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n  content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n  content: \"\\e183\";\n}\n.glyphicon-tower:before {\n  content: \"\\e184\";\n}\n.glyphicon-stats:before {\n  content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n  content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n  content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n  content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n  content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n  content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n  content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n  content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n  content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n  content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n  content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n  content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n  content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n  content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n  content: \"\\e200\";\n}\n.glyphicon-cd:before {\n  content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n  content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n  content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n  content: \"\\e204\";\n}\n.glyphicon-copy:before {\n  content: \"\\e205\";\n}\n.glyphicon-paste:before {\n  content: \"\\e206\";\n}\n.glyphicon-alert:before {\n  content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n  content: \"\\e210\";\n}\n.glyphicon-king:before {\n  content: \"\\e211\";\n}\n.glyphicon-queen:before {\n  content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n  content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n  content: \"\\e214\";\n}\n.glyphicon-knight:before {\n  content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n  content: \"\\e216\";\n}\n.glyphicon-tent:before {\n  content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n  content: \"\\e218\";\n}\n.glyphicon-bed:before {\n  content: \"\\e219\";\n}\n.glyphicon-apple:before {\n  content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n  content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n  content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n  content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n  content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n  content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n  content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n  content: \"\\e227\";\n}\n.glyphicon-btc:before {\n  content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n  content: \"\\e227\";\n}\n.glyphicon-yen:before {\n  content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n  content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n  content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n  content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n  content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n  content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n  content: \"\\e232\";\n}\n.glyphicon-education:before {\n  content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n  content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n  content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n  content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n  content: \"\\e237\";\n}\n.glyphicon-oil:before {\n  content: \"\\e238\";\n}\n.glyphicon-grain:before {\n  content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n  content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n  content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n  content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n  content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n  content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n  content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n  content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n  content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n  content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n  content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n  content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n  content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n  content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n  content: \"\\e253\";\n}\n.glyphicon-console:before {\n  content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n  content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n  content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n  content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n  content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n  content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n  content: \"\\e260\";\n}\n* {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\nhtml {\n  font-size: 10px;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #333333;\n  background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\na {\n  color: #337ab7;\n  text-decoration: none;\n}\na:hover,\na:focus {\n  color: #23527c;\n  text-decoration: underline;\n}\na:focus {\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\nfigure {\n  margin: 0;\n}\nimg {\n  vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  display: block;\n  max-width: 100%;\n  height: auto;\n}\n.img-rounded {\n  border-radius: 6px;\n}\n.img-thumbnail {\n  padding: 4px;\n  line-height: 1.42857143;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 4px;\n  -webkit-transition: all 0.2s ease-in-out;\n  -o-transition: all 0.2s ease-in-out;\n  transition: all 0.2s ease-in-out;\n  display: inline-block;\n  max-width: 100%;\n  height: auto;\n}\n.img-circle {\n  border-radius: 50%;\n}\nhr {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n}\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n  position: static;\n  width: auto;\n  height: auto;\n  margin: 0;\n  overflow: visible;\n  clip: auto;\n}\n[role=\"button\"] {\n  cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n  font-family: inherit;\n  font-weight: 500;\n  line-height: 1.1;\n  color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n  font-weight: 400;\n  line-height: 1;\n  color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n  font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n  font-size: 75%;\n}\nh1,\n.h1 {\n  font-size: 36px;\n}\nh2,\n.h2 {\n  font-size: 30px;\n}\nh3,\n.h3 {\n  font-size: 24px;\n}\nh4,\n.h4 {\n  font-size: 18px;\n}\nh5,\n.h5 {\n  font-size: 14px;\n}\nh6,\n.h6 {\n  font-size: 12px;\n}\np {\n  margin: 0 0 10px;\n}\n.lead {\n  margin-bottom: 20px;\n  font-size: 16px;\n  font-weight: 300;\n  line-height: 1.4;\n}\n@media (min-width: 768px) {\n  .lead {\n    font-size: 21px;\n  }\n}\nsmall,\n.small {\n  font-size: 85%;\n}\nmark,\n.mark {\n  padding: 0.2em;\n  background-color: #fcf8e3;\n}\n.text-left {\n  text-align: left;\n}\n.text-right {\n  text-align: right;\n}\n.text-center {\n  text-align: center;\n}\n.text-justify {\n  text-align: justify;\n}\n.text-nowrap {\n  white-space: nowrap;\n}\n.text-lowercase {\n  text-transform: lowercase;\n}\n.text-uppercase {\n  text-transform: uppercase;\n}\n.text-capitalize {\n  text-transform: capitalize;\n}\n.text-muted {\n  color: #777777;\n}\n.text-primary {\n  color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n  color: #286090;\n}\n.text-success {\n  color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n  color: #2b542c;\n}\n.text-info {\n  color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n  color: #245269;\n}\n.text-warning {\n  color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n  color: #66512c;\n}\n.text-danger {\n  color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n  color: #843534;\n}\n.bg-primary {\n  color: #fff;\n  background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n  background-color: #286090;\n}\n.bg-success {\n  background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n  background-color: #c1e2b3;\n}\n.bg-info {\n  background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n  background-color: #afd9ee;\n}\n.bg-warning {\n  background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n  background-color: #f7ecb5;\n}\n.bg-danger {\n  background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n  background-color: #e4b9b9;\n}\n.page-header {\n  padding-bottom: 9px;\n  margin: 40px 0 20px;\n  border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n  margin-bottom: 0;\n}\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n.list-inline {\n  padding-left: 0;\n  list-style: none;\n  margin-left: -5px;\n}\n.list-inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\ndl {\n  margin-top: 0;\n  margin-bottom: 20px;\n}\ndt,\ndd {\n  line-height: 1.42857143;\n}\ndt {\n  font-weight: 700;\n}\ndd {\n  margin-left: 0;\n}\n@media (min-width: 768px) {\n  .dl-horizontal dt {\n    float: left;\n    width: 160px;\n    clear: left;\n    text-align: right;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n  .dl-horizontal dd {\n    margin-left: 180px;\n  }\n}\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n}\n.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\nblockquote {\n  padding: 10px 20px;\n  margin: 0 0 20px;\n  font-size: 17.5px;\n  border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n  margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n  display: block;\n  font-size: 80%;\n  line-height: 1.42857143;\n  color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n  content: \"\\2014 \\00A0\";\n}\n.blockquote-reverse,\nblockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  text-align: right;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n  content: \"\";\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n  content: \"\\00A0 \\2014\";\n}\naddress {\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n  font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: #c7254e;\n  background-color: #f9f2f4;\n  border-radius: 4px;\n}\nkbd {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: #fff;\n  background-color: #333;\n  border-radius: 3px;\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n  padding: 0;\n  font-size: 100%;\n  font-weight: 700;\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 1.42857143;\n  color: #333333;\n  word-break: break-all;\n  word-wrap: break-word;\n  background-color: #f5f5f5;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n}\npre code {\n  padding: 0;\n  font-size: inherit;\n  color: inherit;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border-radius: 0;\n}\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n.container {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n@media (min-width: 768px) {\n  .container {\n    width: 750px;\n  }\n}\n@media (min-width: 992px) {\n  .container {\n    width: 970px;\n  }\n}\n@media (min-width: 1200px) {\n  .container {\n    width: 1170px;\n  }\n}\n.container-fluid {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n.row {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n.row-no-gutters {\n  margin-right: 0;\n  margin-left: 0;\n}\n.row-no-gutters [class*=\"col-\"] {\n  padding-right: 0;\n  padding-left: 0;\n}\n.col-xs-1,\n.col-sm-1,\n.col-md-1,\n.col-lg-1,\n.col-xs-2,\n.col-sm-2,\n.col-md-2,\n.col-lg-2,\n.col-xs-3,\n.col-sm-3,\n.col-md-3,\n.col-lg-3,\n.col-xs-4,\n.col-sm-4,\n.col-md-4,\n.col-lg-4,\n.col-xs-5,\n.col-sm-5,\n.col-md-5,\n.col-lg-5,\n.col-xs-6,\n.col-sm-6,\n.col-md-6,\n.col-lg-6,\n.col-xs-7,\n.col-sm-7,\n.col-md-7,\n.col-lg-7,\n.col-xs-8,\n.col-sm-8,\n.col-md-8,\n.col-lg-8,\n.col-xs-9,\n.col-sm-9,\n.col-md-9,\n.col-lg-9,\n.col-xs-10,\n.col-sm-10,\n.col-md-10,\n.col-lg-10,\n.col-xs-11,\n.col-sm-11,\n.col-md-11,\n.col-lg-11,\n.col-xs-12,\n.col-sm-12,\n.col-md-12,\n.col-lg-12 {\n  position: relative;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11,\n.col-xs-12 {\n  float: left;\n}\n.col-xs-12 {\n  width: 100%;\n}\n.col-xs-11 {\n  width: 91.66666667%;\n}\n.col-xs-10 {\n  width: 83.33333333%;\n}\n.col-xs-9 {\n  width: 75%;\n}\n.col-xs-8 {\n  width: 66.66666667%;\n}\n.col-xs-7 {\n  width: 58.33333333%;\n}\n.col-xs-6 {\n  width: 50%;\n}\n.col-xs-5 {\n  width: 41.66666667%;\n}\n.col-xs-4 {\n  width: 33.33333333%;\n}\n.col-xs-3 {\n  width: 25%;\n}\n.col-xs-2 {\n  width: 16.66666667%;\n}\n.col-xs-1 {\n  width: 8.33333333%;\n}\n.col-xs-pull-12 {\n  right: 100%;\n}\n.col-xs-pull-11 {\n  right: 91.66666667%;\n}\n.col-xs-pull-10 {\n  right: 83.33333333%;\n}\n.col-xs-pull-9 {\n  right: 75%;\n}\n.col-xs-pull-8 {\n  right: 66.66666667%;\n}\n.col-xs-pull-7 {\n  right: 58.33333333%;\n}\n.col-xs-pull-6 {\n  right: 50%;\n}\n.col-xs-pull-5 {\n  right: 41.66666667%;\n}\n.col-xs-pull-4 {\n  right: 33.33333333%;\n}\n.col-xs-pull-3 {\n  right: 25%;\n}\n.col-xs-pull-2 {\n  right: 16.66666667%;\n}\n.col-xs-pull-1 {\n  right: 8.33333333%;\n}\n.col-xs-pull-0 {\n  right: auto;\n}\n.col-xs-push-12 {\n  left: 100%;\n}\n.col-xs-push-11 {\n  left: 91.66666667%;\n}\n.col-xs-push-10 {\n  left: 83.33333333%;\n}\n.col-xs-push-9 {\n  left: 75%;\n}\n.col-xs-push-8 {\n  left: 66.66666667%;\n}\n.col-xs-push-7 {\n  left: 58.33333333%;\n}\n.col-xs-push-6 {\n  left: 50%;\n}\n.col-xs-push-5 {\n  left: 41.66666667%;\n}\n.col-xs-push-4 {\n  left: 33.33333333%;\n}\n.col-xs-push-3 {\n  left: 25%;\n}\n.col-xs-push-2 {\n  left: 16.66666667%;\n}\n.col-xs-push-1 {\n  left: 8.33333333%;\n}\n.col-xs-push-0 {\n  left: auto;\n}\n.col-xs-offset-12 {\n  margin-left: 100%;\n}\n.col-xs-offset-11 {\n  margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n  margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n  margin-left: 75%;\n}\n.col-xs-offset-8 {\n  margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n  margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n  margin-left: 50%;\n}\n.col-xs-offset-5 {\n  margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n  margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n  margin-left: 25%;\n}\n.col-xs-offset-2 {\n  margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n  margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n  margin-left: 0%;\n}\n@media (min-width: 768px) {\n  .col-sm-1,\n  .col-sm-2,\n  .col-sm-3,\n  .col-sm-4,\n  .col-sm-5,\n  .col-sm-6,\n  .col-sm-7,\n  .col-sm-8,\n  .col-sm-9,\n  .col-sm-10,\n  .col-sm-11,\n  .col-sm-12 {\n    float: left;\n  }\n  .col-sm-12 {\n    width: 100%;\n  }\n  .col-sm-11 {\n    width: 91.66666667%;\n  }\n  .col-sm-10 {\n    width: 83.33333333%;\n  }\n  .col-sm-9 {\n    width: 75%;\n  }\n  .col-sm-8 {\n    width: 66.66666667%;\n  }\n  .col-sm-7 {\n    width: 58.33333333%;\n  }\n  .col-sm-6 {\n    width: 50%;\n  }\n  .col-sm-5 {\n    width: 41.66666667%;\n  }\n  .col-sm-4 {\n    width: 33.33333333%;\n  }\n  .col-sm-3 {\n    width: 25%;\n  }\n  .col-sm-2 {\n    width: 16.66666667%;\n  }\n  .col-sm-1 {\n    width: 8.33333333%;\n  }\n  .col-sm-pull-12 {\n    right: 100%;\n  }\n  .col-sm-pull-11 {\n    right: 91.66666667%;\n  }\n  .col-sm-pull-10 {\n    right: 83.33333333%;\n  }\n  .col-sm-pull-9 {\n    right: 75%;\n  }\n  .col-sm-pull-8 {\n    right: 66.66666667%;\n  }\n  .col-sm-pull-7 {\n    right: 58.33333333%;\n  }\n  .col-sm-pull-6 {\n    right: 50%;\n  }\n  .col-sm-pull-5 {\n    right: 41.66666667%;\n  }\n  .col-sm-pull-4 {\n    right: 33.33333333%;\n  }\n  .col-sm-pull-3 {\n    right: 25%;\n  }\n  .col-sm-pull-2 {\n    right: 16.66666667%;\n  }\n  .col-sm-pull-1 {\n    right: 8.33333333%;\n  }\n  .col-sm-pull-0 {\n    right: auto;\n  }\n  .col-sm-push-12 {\n    left: 100%;\n  }\n  .col-sm-push-11 {\n    left: 91.66666667%;\n  }\n  .col-sm-push-10 {\n    left: 83.33333333%;\n  }\n  .col-sm-push-9 {\n    left: 75%;\n  }\n  .col-sm-push-8 {\n    left: 66.66666667%;\n  }\n  .col-sm-push-7 {\n    left: 58.33333333%;\n  }\n  .col-sm-push-6 {\n    left: 50%;\n  }\n  .col-sm-push-5 {\n    left: 41.66666667%;\n  }\n  .col-sm-push-4 {\n    left: 33.33333333%;\n  }\n  .col-sm-push-3 {\n    left: 25%;\n  }\n  .col-sm-push-2 {\n    left: 16.66666667%;\n  }\n  .col-sm-push-1 {\n    left: 8.33333333%;\n  }\n  .col-sm-push-0 {\n    left: auto;\n  }\n  .col-sm-offset-12 {\n    margin-left: 100%;\n  }\n  .col-sm-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .col-sm-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .col-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .col-sm-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .col-sm-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .col-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .col-sm-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .col-sm-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .col-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .col-sm-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .col-sm-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .col-sm-offset-0 {\n    margin-left: 0%;\n  }\n}\n@media (min-width: 992px) {\n  .col-md-1,\n  .col-md-2,\n  .col-md-3,\n  .col-md-4,\n  .col-md-5,\n  .col-md-6,\n  .col-md-7,\n  .col-md-8,\n  .col-md-9,\n  .col-md-10,\n  .col-md-11,\n  .col-md-12 {\n    float: left;\n  }\n  .col-md-12 {\n    width: 100%;\n  }\n  .col-md-11 {\n    width: 91.66666667%;\n  }\n  .col-md-10 {\n    width: 83.33333333%;\n  }\n  .col-md-9 {\n    width: 75%;\n  }\n  .col-md-8 {\n    width: 66.66666667%;\n  }\n  .col-md-7 {\n    width: 58.33333333%;\n  }\n  .col-md-6 {\n    width: 50%;\n  }\n  .col-md-5 {\n    width: 41.66666667%;\n  }\n  .col-md-4 {\n    width: 33.33333333%;\n  }\n  .col-md-3 {\n    width: 25%;\n  }\n  .col-md-2 {\n    width: 16.66666667%;\n  }\n  .col-md-1 {\n    width: 8.33333333%;\n  }\n  .col-md-pull-12 {\n    right: 100%;\n  }\n  .col-md-pull-11 {\n    right: 91.66666667%;\n  }\n  .col-md-pull-10 {\n    right: 83.33333333%;\n  }\n  .col-md-pull-9 {\n    right: 75%;\n  }\n  .col-md-pull-8 {\n    right: 66.66666667%;\n  }\n  .col-md-pull-7 {\n    right: 58.33333333%;\n  }\n  .col-md-pull-6 {\n    right: 50%;\n  }\n  .col-md-pull-5 {\n    right: 41.66666667%;\n  }\n  .col-md-pull-4 {\n    right: 33.33333333%;\n  }\n  .col-md-pull-3 {\n    right: 25%;\n  }\n  .col-md-pull-2 {\n    right: 16.66666667%;\n  }\n  .col-md-pull-1 {\n    right: 8.33333333%;\n  }\n  .col-md-pull-0 {\n    right: auto;\n  }\n  .col-md-push-12 {\n    left: 100%;\n  }\n  .col-md-push-11 {\n    left: 91.66666667%;\n  }\n  .col-md-push-10 {\n    left: 83.33333333%;\n  }\n  .col-md-push-9 {\n    left: 75%;\n  }\n  .col-md-push-8 {\n    left: 66.66666667%;\n  }\n  .col-md-push-7 {\n    left: 58.33333333%;\n  }\n  .col-md-push-6 {\n    left: 50%;\n  }\n  .col-md-push-5 {\n    left: 41.66666667%;\n  }\n  .col-md-push-4 {\n    left: 33.33333333%;\n  }\n  .col-md-push-3 {\n    left: 25%;\n  }\n  .col-md-push-2 {\n    left: 16.66666667%;\n  }\n  .col-md-push-1 {\n    left: 8.33333333%;\n  }\n  .col-md-push-0 {\n    left: auto;\n  }\n  .col-md-offset-12 {\n    margin-left: 100%;\n  }\n  .col-md-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .col-md-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .col-md-offset-9 {\n    margin-left: 75%;\n  }\n  .col-md-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .col-md-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .col-md-offset-6 {\n    margin-left: 50%;\n  }\n  .col-md-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .col-md-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .col-md-offset-3 {\n    margin-left: 25%;\n  }\n  .col-md-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .col-md-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .col-md-offset-0 {\n    margin-left: 0%;\n  }\n}\n@media (min-width: 1200px) {\n  .col-lg-1,\n  .col-lg-2,\n  .col-lg-3,\n  .col-lg-4,\n  .col-lg-5,\n  .col-lg-6,\n  .col-lg-7,\n  .col-lg-8,\n  .col-lg-9,\n  .col-lg-10,\n  .col-lg-11,\n  .col-lg-12 {\n    float: left;\n  }\n  .col-lg-12 {\n    width: 100%;\n  }\n  .col-lg-11 {\n    width: 91.66666667%;\n  }\n  .col-lg-10 {\n    width: 83.33333333%;\n  }\n  .col-lg-9 {\n    width: 75%;\n  }\n  .col-lg-8 {\n    width: 66.66666667%;\n  }\n  .col-lg-7 {\n    width: 58.33333333%;\n  }\n  .col-lg-6 {\n    width: 50%;\n  }\n  .col-lg-5 {\n    width: 41.66666667%;\n  }\n  .col-lg-4 {\n    width: 33.33333333%;\n  }\n  .col-lg-3 {\n    width: 25%;\n  }\n  .col-lg-2 {\n    width: 16.66666667%;\n  }\n  .col-lg-1 {\n    width: 8.33333333%;\n  }\n  .col-lg-pull-12 {\n    right: 100%;\n  }\n  .col-lg-pull-11 {\n    right: 91.66666667%;\n  }\n  .col-lg-pull-10 {\n    right: 83.33333333%;\n  }\n  .col-lg-pull-9 {\n    right: 75%;\n  }\n  .col-lg-pull-8 {\n    right: 66.66666667%;\n  }\n  .col-lg-pull-7 {\n    right: 58.33333333%;\n  }\n  .col-lg-pull-6 {\n    right: 50%;\n  }\n  .col-lg-pull-5 {\n    right: 41.66666667%;\n  }\n  .col-lg-pull-4 {\n    right: 33.33333333%;\n  }\n  .col-lg-pull-3 {\n    right: 25%;\n  }\n  .col-lg-pull-2 {\n    right: 16.66666667%;\n  }\n  .col-lg-pull-1 {\n    right: 8.33333333%;\n  }\n  .col-lg-pull-0 {\n    right: auto;\n  }\n  .col-lg-push-12 {\n    left: 100%;\n  }\n  .col-lg-push-11 {\n    left: 91.66666667%;\n  }\n  .col-lg-push-10 {\n    left: 83.33333333%;\n  }\n  .col-lg-push-9 {\n    left: 75%;\n  }\n  .col-lg-push-8 {\n    left: 66.66666667%;\n  }\n  .col-lg-push-7 {\n    left: 58.33333333%;\n  }\n  .col-lg-push-6 {\n    left: 50%;\n  }\n  .col-lg-push-5 {\n    left: 41.66666667%;\n  }\n  .col-lg-push-4 {\n    left: 33.33333333%;\n  }\n  .col-lg-push-3 {\n    left: 25%;\n  }\n  .col-lg-push-2 {\n    left: 16.66666667%;\n  }\n  .col-lg-push-1 {\n    left: 8.33333333%;\n  }\n  .col-lg-push-0 {\n    left: auto;\n  }\n  .col-lg-offset-12 {\n    margin-left: 100%;\n  }\n  .col-lg-offset-11 {\n    margin-left: 91.66666667%;\n  }\n  .col-lg-offset-10 {\n    margin-left: 83.33333333%;\n  }\n  .col-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .col-lg-offset-8 {\n    margin-left: 66.66666667%;\n  }\n  .col-lg-offset-7 {\n    margin-left: 58.33333333%;\n  }\n  .col-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .col-lg-offset-5 {\n    margin-left: 41.66666667%;\n  }\n  .col-lg-offset-4 {\n    margin-left: 33.33333333%;\n  }\n  .col-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .col-lg-offset-2 {\n    margin-left: 16.66666667%;\n  }\n  .col-lg-offset-1 {\n    margin-left: 8.33333333%;\n  }\n  .col-lg-offset-0 {\n    margin-left: 0%;\n  }\n}\ntable {\n  background-color: transparent;\n}\ntable col[class*=\"col-\"] {\n  position: static;\n  display: table-column;\n  float: none;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n  position: static;\n  display: table-cell;\n  float: none;\n}\ncaption {\n  padding-top: 8px;\n  padding-bottom: 8px;\n  color: #777777;\n  text-align: left;\n}\nth {\n  text-align: left;\n}\n.table {\n  width: 100%;\n  max-width: 100%;\n  margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n  padding: 8px;\n  line-height: 1.42857143;\n  vertical-align: top;\n  border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n  vertical-align: bottom;\n  border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n  border-top: 0;\n}\n.table > tbody + tbody {\n  border-top: 2px solid #ddd;\n}\n.table .table {\n  background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n  padding: 5px;\n}\n.table-bordered {\n  border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n  border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n  border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n  background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n  background-color: #f5f5f5;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n  background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n  background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n  background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n  background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n  background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n  background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n  background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n  background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n  background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n  background-color: #ebcccc;\n}\n.table-responsive {\n  min-height: 0.01%;\n  overflow-x: auto;\n}\n@media screen and (max-width: 767px) {\n  .table-responsive {\n    width: 100%;\n    margin-bottom: 15px;\n    overflow-y: hidden;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n    border: 1px solid #ddd;\n  }\n  .table-responsive > .table {\n    margin-bottom: 0;\n  }\n  .table-responsive > .table > thead > tr > th,\n  .table-responsive > .table > tbody > tr > th,\n  .table-responsive > .table > tfoot > tr > th,\n  .table-responsive > .table > thead > tr > td,\n  .table-responsive > .table > tbody > tr > td,\n  .table-responsive > .table > tfoot > tr > td {\n    white-space: nowrap;\n  }\n  .table-responsive > .table-bordered {\n    border: 0;\n  }\n  .table-responsive > .table-bordered > thead > tr > th:first-child,\n  .table-responsive > .table-bordered > tbody > tr > th:first-child,\n  .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n  .table-responsive > .table-bordered > thead > tr > td:first-child,\n  .table-responsive > .table-bordered > tbody > tr > td:first-child,\n  .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n    border-left: 0;\n  }\n  .table-responsive > .table-bordered > thead > tr > th:last-child,\n  .table-responsive > .table-bordered > tbody > tr > th:last-child,\n  .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n  .table-responsive > .table-bordered > thead > tr > td:last-child,\n  .table-responsive > .table-bordered > tbody > tr > td:last-child,\n  .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n    border-right: 0;\n  }\n  .table-responsive > .table-bordered > tbody > tr:last-child > th,\n  .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n  .table-responsive > .table-bordered > tbody > tr:last-child > td,\n  .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n    border-bottom: 0;\n  }\n}\nfieldset {\n  min-width: 0;\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: inherit;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n  display: inline-block;\n  max-width: 100%;\n  margin-bottom: 5px;\n  font-weight: 700;\n}\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  line-height: normal;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n  cursor: not-allowed;\n}\ninput[type=\"file\"] {\n  display: block;\n}\ninput[type=\"range\"] {\n  display: block;\n  width: 100%;\n}\nselect[multiple],\nselect[size] {\n  height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\noutput {\n  display: block;\n  padding-top: 7px;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #555555;\n}\n.form-control {\n  display: block;\n  width: 100%;\n  height: 34px;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.42857143;\n  color: #555555;\n  background-color: #fff;\n  background-image: none;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n  -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n  -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;\n  transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;\n  transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n  transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n  border-color: #66afe9;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n  color: #999;\n  opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n  color: #999;\n}\n.form-control::-webkit-input-placeholder {\n  color: #999;\n}\n.form-control::-ms-expand {\n  background-color: transparent;\n  border: 0;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n  background-color: #eeeeee;\n  opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n  cursor: not-allowed;\n}\ntextarea.form-control {\n  height: auto;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n  input[type=\"date\"].form-control,\n  input[type=\"time\"].form-control,\n  input[type=\"datetime-local\"].form-control,\n  input[type=\"month\"].form-control {\n    line-height: 34px;\n  }\n  input[type=\"date\"].input-sm,\n  input[type=\"time\"].input-sm,\n  input[type=\"datetime-local\"].input-sm,\n  input[type=\"month\"].input-sm,\n  .input-group-sm input[type=\"date\"],\n  .input-group-sm input[type=\"time\"],\n  .input-group-sm input[type=\"datetime-local\"],\n  .input-group-sm input[type=\"month\"] {\n    line-height: 30px;\n  }\n  input[type=\"date\"].input-lg,\n  input[type=\"time\"].input-lg,\n  input[type=\"datetime-local\"].input-lg,\n  input[type=\"month\"].input-lg,\n  .input-group-lg input[type=\"date\"],\n  .input-group-lg input[type=\"time\"],\n  .input-group-lg input[type=\"datetime-local\"],\n  .input-group-lg input[type=\"month\"] {\n    line-height: 46px;\n  }\n}\n.form-group {\n  margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n  position: relative;\n  display: block;\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n  cursor: not-allowed;\n}\n.radio label,\n.checkbox label {\n  min-height: 20px;\n  padding-left: 20px;\n  margin-bottom: 0;\n  font-weight: 400;\n  cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n  position: absolute;\n  margin-top: 4px \\9;\n  margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n  position: relative;\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  font-weight: 400;\n  vertical-align: middle;\n  cursor: pointer;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n  cursor: not-allowed;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\n.form-control-static {\n  min-height: 34px;\n  padding-top: 7px;\n  padding-bottom: 7px;\n  margin-bottom: 0;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n  padding-right: 0;\n  padding-left: 0;\n}\n.input-sm {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\nselect.input-sm {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n  height: auto;\n}\n.form-group-sm .form-control {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.form-group-sm select.form-control {\n  height: 30px;\n  line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n  height: auto;\n}\n.form-group-sm .form-control-static {\n  height: 30px;\n  min-height: 32px;\n  padding: 6px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n}\n.input-lg {\n  height: 46px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.3333333;\n  border-radius: 6px;\n}\nselect.input-lg {\n  height: 46px;\n  line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n  height: auto;\n}\n.form-group-lg .form-control {\n  height: 46px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.3333333;\n  border-radius: 6px;\n}\n.form-group-lg select.form-control {\n  height: 46px;\n  line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n  height: auto;\n}\n.form-group-lg .form-control-static {\n  height: 46px;\n  min-height: 38px;\n  padding: 11px 16px;\n  font-size: 18px;\n  line-height: 1.3333333;\n}\n.has-feedback {\n  position: relative;\n}\n.has-feedback .form-control {\n  padding-right: 42.5px;\n}\n.form-control-feedback {\n  position: absolute;\n  top: 0;\n  right: 0;\n  z-index: 2;\n  display: block;\n  width: 34px;\n  height: 34px;\n  line-height: 34px;\n  text-align: center;\n  pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n  width: 46px;\n  height: 46px;\n  line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n  width: 30px;\n  height: 30px;\n  line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n  color: #3c763d;\n}\n.has-success .form-control {\n  border-color: #3c763d;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n  border-color: #2b542c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #3c763d;\n}\n.has-success .form-control-feedback {\n  color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n  color: #8a6d3b;\n}\n.has-warning .form-control {\n  border-color: #8a6d3b;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n  border-color: #66512c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #8a6d3b;\n}\n.has-warning .form-control-feedback {\n  color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n  color: #a94442;\n}\n.has-error .form-control {\n  border-color: #a94442;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n  border-color: #843534;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #a94442;\n}\n.has-error .form-control-feedback {\n  color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n  top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n  top: 0;\n}\n.help-block {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #737373;\n}\n@media (min-width: 768px) {\n  .form-inline .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .form-inline .form-control {\n    display: inline-block;\n    width: auto;\n    vertical-align: middle;\n  }\n  .form-inline .form-control-static {\n    display: inline-block;\n  }\n  .form-inline .input-group {\n    display: inline-table;\n    vertical-align: middle;\n  }\n  .form-inline .input-group .input-group-addon,\n  .form-inline .input-group .input-group-btn,\n  .form-inline .input-group .form-control {\n    width: auto;\n  }\n  .form-inline .input-group > .form-control {\n    width: 100%;\n  }\n  .form-inline .control-label {\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .form-inline .radio,\n  .form-inline .checkbox {\n    display: inline-block;\n    margin-top: 0;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .form-inline .radio label,\n  .form-inline .checkbox label {\n    padding-left: 0;\n  }\n  .form-inline .radio input[type=\"radio\"],\n  .form-inline .checkbox input[type=\"checkbox\"] {\n    position: relative;\n    margin-left: 0;\n  }\n  .form-inline .has-feedback .form-control-feedback {\n    top: 0;\n  }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n  padding-top: 7px;\n  margin-top: 0;\n  margin-bottom: 0;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n  min-height: 27px;\n}\n.form-horizontal .form-group {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n@media (min-width: 768px) {\n  .form-horizontal .control-label {\n    padding-top: 7px;\n    margin-bottom: 0;\n    text-align: right;\n  }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n  right: 15px;\n}\n@media (min-width: 768px) {\n  .form-horizontal .form-group-lg .control-label {\n    padding-top: 11px;\n    font-size: 18px;\n  }\n}\n@media (min-width: 768px) {\n  .form-horizontal .form-group-sm .control-label {\n    padding-top: 6px;\n    font-size: 12px;\n  }\n}\n.btn {\n  display: inline-block;\n  margin-bottom: 0;\n  font-weight: normal;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  -ms-touch-action: manipulation;\n  touch-action: manipulation;\n  cursor: pointer;\n  background-image: none;\n  border: 1px solid transparent;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.42857143;\n  border-radius: 4px;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n  color: #333;\n  text-decoration: none;\n}\n.btn:active,\n.btn.active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n  cursor: not-allowed;\n  filter: alpha(opacity=65);\n  opacity: 0.65;\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n  pointer-events: none;\n}\n.btn-default {\n  color: #333;\n  background-color: #fff;\n  border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n  color: #333;\n  background-color: #e6e6e6;\n  border-color: #8c8c8c;\n}\n.btn-default:hover {\n  color: #333;\n  background-color: #e6e6e6;\n  border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n  color: #333;\n  background-color: #e6e6e6;\n  background-image: none;\n  border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n  color: #333;\n  background-color: #d4d4d4;\n  border-color: #8c8c8c;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n  background-color: #fff;\n  border-color: #ccc;\n}\n.btn-default .badge {\n  color: #fff;\n  background-color: #333;\n}\n.btn-primary {\n  color: #fff;\n  background-color: #337ab7;\n  border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n  color: #fff;\n  background-color: #286090;\n  border-color: #122b40;\n}\n.btn-primary:hover {\n  color: #fff;\n  background-color: #286090;\n  border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n  color: #fff;\n  background-color: #286090;\n  background-image: none;\n  border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n  color: #fff;\n  background-color: #204d74;\n  border-color: #122b40;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n  background-color: #337ab7;\n  border-color: #2e6da4;\n}\n.btn-primary .badge {\n  color: #337ab7;\n  background-color: #fff;\n}\n.btn-success {\n  color: #fff;\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n  color: #fff;\n  background-color: #449d44;\n  border-color: #255625;\n}\n.btn-success:hover {\n  color: #fff;\n  background-color: #449d44;\n  border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n  color: #fff;\n  background-color: #449d44;\n  background-image: none;\n  border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n  color: #fff;\n  background-color: #398439;\n  border-color: #255625;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n.btn-success .badge {\n  color: #5cb85c;\n  background-color: #fff;\n}\n.btn-info {\n  color: #fff;\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n  color: #fff;\n  background-color: #31b0d5;\n  border-color: #1b6d85;\n}\n.btn-info:hover {\n  color: #fff;\n  background-color: #31b0d5;\n  border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n  color: #fff;\n  background-color: #31b0d5;\n  background-image: none;\n  border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n  color: #fff;\n  background-color: #269abc;\n  border-color: #1b6d85;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n.btn-info .badge {\n  color: #5bc0de;\n  background-color: #fff;\n}\n.btn-warning {\n  color: #fff;\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n  color: #fff;\n  background-color: #ec971f;\n  border-color: #985f0d;\n}\n.btn-warning:hover {\n  color: #fff;\n  background-color: #ec971f;\n  border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n  color: #fff;\n  background-color: #ec971f;\n  background-image: none;\n  border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n  color: #fff;\n  background-color: #d58512;\n  border-color: #985f0d;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n.btn-warning .badge {\n  color: #f0ad4e;\n  background-color: #fff;\n}\n.btn-danger {\n  color: #fff;\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n  color: #fff;\n  background-color: #c9302c;\n  border-color: #761c19;\n}\n.btn-danger:hover {\n  color: #fff;\n  background-color: #c9302c;\n  border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n  color: #fff;\n  background-color: #c9302c;\n  background-image: none;\n  border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n  color: #fff;\n  background-color: #ac2925;\n  border-color: #761c19;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n.btn-danger .badge {\n  color: #d9534f;\n  background-color: #fff;\n}\n.btn-link {\n  font-weight: 400;\n  color: #337ab7;\n  border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n  background-color: transparent;\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n  border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n  color: #23527c;\n  text-decoration: underline;\n  background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n  color: #777777;\n  text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.3333333;\n  border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n  padding: 1px 5px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n.btn-block {\n  display: block;\n  width: 100%;\n}\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n  -o-transition: opacity 0.15s linear;\n  transition: opacity 0.15s linear;\n}\n.fade.in {\n  opacity: 1;\n}\n.collapse {\n  display: none;\n}\n.collapse.in {\n  display: block;\n}\ntr.collapse.in {\n  display: table-row;\n}\ntbody.collapse.in {\n  display: table-row-group;\n}\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition-property: height, visibility;\n  -o-transition-property: height, visibility;\n  transition-property: height, visibility;\n  -webkit-transition-duration: 0.35s;\n  -o-transition-duration: 0.35s;\n  transition-duration: 0.35s;\n  -webkit-transition-timing-function: ease;\n  -o-transition-timing-function: ease;\n  transition-timing-function: ease;\n}\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 2px;\n  vertical-align: middle;\n  border-top: 4px dashed;\n  border-top: 4px solid \\9;\n  border-right: 4px solid transparent;\n  border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n  position: relative;\n}\n.dropdown-toggle:focus {\n  outline: 0;\n}\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  font-size: 14px;\n  text-align: left;\n  list-style: none;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  border-radius: 4px;\n  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n}\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n.dropdown-menu .divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: 400;\n  line-height: 1.42857143;\n  color: #333333;\n  white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  color: #262626;\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  color: #fff;\n  text-decoration: none;\n  background-color: #337ab7;\n  outline: 0;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.open > .dropdown-menu {\n  display: block;\n}\n.open > a {\n  outline: 0;\n}\n.dropdown-menu-right {\n  right: 0;\n  left: auto;\n}\n.dropdown-menu-left {\n  right: auto;\n  left: 0;\n}\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: 12px;\n  line-height: 1.42857143;\n  color: #777777;\n  white-space: nowrap;\n}\n.dropdown-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 990;\n}\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  content: \"\";\n  border-top: 0;\n  border-bottom: 4px dashed;\n  border-bottom: 4px solid \\9;\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n  .navbar-right .dropdown-menu {\n    right: 0;\n    left: auto;\n  }\n  .navbar-right .dropdown-menu-left {\n    right: auto;\n    left: 0;\n  }\n}\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n  z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n  margin-left: -1px;\n}\n.btn-toolbar {\n  margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n  float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n  margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n.btn-group > .btn:first-child {\n  margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group > .btn-group {\n  float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n  padding-right: 8px;\n  padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n  padding-right: 12px;\n  padding-left: 12px;\n}\n.btn-group.open .dropdown-toggle {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n  box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\n.btn .caret {\n  margin-left: 0;\n}\n.btn-lg .caret {\n  border-width: 5px 5px 0;\n  border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n  border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n  float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n  margin-top: -1px;\n  margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n  border-top-left-radius: 4px;\n  border-top-right-radius: 4px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 4px;\n  border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  table-layout: fixed;\n  border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n  width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n  left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n  position: absolute;\n  clip: rect(0, 0, 0, 0);\n  pointer-events: none;\n}\n.input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n  float: none;\n  padding-right: 0;\n  padding-left: 0;\n}\n.input-group .form-control {\n  position: relative;\n  z-index: 2;\n  float: left;\n  width: 100%;\n  margin-bottom: 0;\n}\n.input-group .form-control:focus {\n  z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  height: 46px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.3333333;\n  border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n  height: 46px;\n  line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n  height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n  height: 30px;\n  line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n  height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n.input-group-addon {\n  padding: 6px 12px;\n  font-size: 14px;\n  font-weight: 400;\n  line-height: 1;\n  color: #555555;\n  text-align: center;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n}\n.input-group-addon.input-sm {\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n.input-group-addon.input-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n  margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n.input-group-addon:first-child {\n  border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n  border-top-left-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.input-group-addon:last-child {\n  border-left: 0;\n}\n.input-group-btn {\n  position: relative;\n  font-size: 0;\n  white-space: nowrap;\n}\n.input-group-btn > .btn {\n  position: relative;\n}\n.input-group-btn > .btn + .btn {\n  margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n  z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n  margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n  z-index: 2;\n  margin-left: -1px;\n}\n.nav {\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n.nav > li {\n  position: relative;\n  display: block;\n}\n.nav > li > a {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n  color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n  color: #777777;\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n  background-color: #eeeeee;\n  border-color: #337ab7;\n}\n.nav .nav-divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n.nav > li > a > img {\n  max-width: none;\n}\n.nav-tabs {\n  border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n  margin-right: 2px;\n  line-height: 1.42857143;\n  border: 1px solid transparent;\n  border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n  color: #555555;\n  cursor: default;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-bottom-color: transparent;\n}\n.nav-tabs.nav-justified {\n  width: 100%;\n  border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n  float: none;\n}\n.nav-tabs.nav-justified > li > a {\n  margin-bottom: 5px;\n  text-align: center;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\n}\n@media (min-width: 768px) {\n  .nav-tabs.nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .nav-tabs.nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n.nav-tabs.nav-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n  border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n  .nav-tabs.nav-justified > li > a {\n    border-bottom: 1px solid #ddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .nav-tabs.nav-justified > .active > a,\n  .nav-tabs.nav-justified > .active > a:hover,\n  .nav-tabs.nav-justified > .active > a:focus {\n    border-bottom-color: #fff;\n  }\n}\n.nav-pills > li {\n  float: left;\n}\n.nav-pills > li > a {\n  border-radius: 4px;\n}\n.nav-pills > li + li {\n  margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n  color: #fff;\n  background-color: #337ab7;\n}\n.nav-stacked > li {\n  float: none;\n}\n.nav-stacked > li + li {\n  margin-top: 2px;\n  margin-left: 0;\n}\n.nav-justified {\n  width: 100%;\n}\n.nav-justified > li {\n  float: none;\n}\n.nav-justified > li > a {\n  margin-bottom: 5px;\n  text-align: center;\n}\n.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\n}\n@media (min-width: 768px) {\n  .nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n.nav-tabs-justified {\n  border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n  border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n  .nav-tabs-justified > li > a {\n    border-bottom: 1px solid #ddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .nav-tabs-justified > .active > a,\n  .nav-tabs-justified > .active > a:hover,\n  .nav-tabs-justified > .active > a:focus {\n    border-bottom-color: #fff;\n  }\n}\n.tab-content > .tab-pane {\n  display: none;\n}\n.tab-content > .active {\n  display: block;\n}\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n.navbar {\n  position: relative;\n  min-height: 50px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n  .navbar {\n    border-radius: 4px;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-header {\n    float: left;\n  }\n}\n.navbar-collapse {\n  padding-right: 15px;\n  padding-left: 15px;\n  overflow-x: visible;\n  border-top: 1px solid transparent;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n  -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n  overflow-y: auto;\n}\n@media (min-width: 768px) {\n  .navbar-collapse {\n    width: auto;\n    border-top: 0;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n  }\n  .navbar-collapse.collapse {\n    display: block !important;\n    height: auto !important;\n    padding-bottom: 0;\n    overflow: visible !important;\n  }\n  .navbar-collapse.in {\n    overflow-y: visible;\n  }\n  .navbar-fixed-top .navbar-collapse,\n  .navbar-static-top .navbar-collapse,\n  .navbar-fixed-bottom .navbar-collapse {\n    padding-right: 0;\n    padding-left: 0;\n  }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n  max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n  .navbar-fixed-top .navbar-collapse,\n  .navbar-fixed-bottom .navbar-collapse {\n    max-height: 200px;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-fixed-top,\n  .navbar-fixed-bottom {\n    border-radius: 0;\n  }\n}\n.navbar-fixed-top {\n  top: 0;\n  border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n  border-width: 1px 0 0;\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n@media (min-width: 768px) {\n  .container > .navbar-header,\n  .container-fluid > .navbar-header,\n  .container > .navbar-collapse,\n  .container-fluid > .navbar-collapse {\n    margin-right: 0;\n    margin-left: 0;\n  }\n}\n.navbar-static-top {\n  z-index: 1000;\n  border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n  .navbar-static-top {\n    border-radius: 0;\n  }\n}\n.navbar-brand {\n  float: left;\n  height: 50px;\n  padding: 15px 15px;\n  font-size: 18px;\n  line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n  text-decoration: none;\n}\n.navbar-brand > img {\n  display: block;\n}\n@media (min-width: 768px) {\n  .navbar > .container .navbar-brand,\n  .navbar > .container-fluid .navbar-brand {\n    margin-left: -15px;\n  }\n}\n.navbar-toggle {\n  position: relative;\n  float: right;\n  padding: 9px 10px;\n  margin-right: 15px;\n  margin-top: 8px;\n  margin-bottom: 8px;\n  background-color: transparent;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.navbar-toggle:focus {\n  outline: 0;\n}\n.navbar-toggle .icon-bar {\n  display: block;\n  width: 22px;\n  height: 2px;\n  border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n  margin-top: 4px;\n}\n@media (min-width: 768px) {\n  .navbar-toggle {\n    display: none;\n  }\n}\n.navbar-nav {\n  margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n  padding-top: 10px;\n  padding-bottom: 10px;\n  line-height: 20px;\n}\n@media (max-width: 767px) {\n  .navbar-nav .open .dropdown-menu {\n    position: static;\n    float: none;\n    width: auto;\n    margin-top: 0;\n    background-color: transparent;\n    border: 0;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n  }\n  .navbar-nav .open .dropdown-menu > li > a,\n  .navbar-nav .open .dropdown-menu .dropdown-header {\n    padding: 5px 15px 5px 25px;\n  }\n  .navbar-nav .open .dropdown-menu > li > a {\n    line-height: 20px;\n  }\n  .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-nav .open .dropdown-menu > li > a:focus {\n    background-image: none;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-nav {\n    float: left;\n    margin: 0;\n  }\n  .navbar-nav > li {\n    float: left;\n  }\n  .navbar-nav > li > a {\n    padding-top: 15px;\n    padding-bottom: 15px;\n  }\n}\n.navbar-form {\n  padding: 10px 15px;\n  margin-right: -15px;\n  margin-left: -15px;\n  border-top: 1px solid transparent;\n  border-bottom: 1px solid transparent;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n  margin-top: 8px;\n  margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n  .navbar-form .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .navbar-form .form-control {\n    display: inline-block;\n    width: auto;\n    vertical-align: middle;\n  }\n  .navbar-form .form-control-static {\n    display: inline-block;\n  }\n  .navbar-form .input-group {\n    display: inline-table;\n    vertical-align: middle;\n  }\n  .navbar-form .input-group .input-group-addon,\n  .navbar-form .input-group .input-group-btn,\n  .navbar-form .input-group .form-control {\n    width: auto;\n  }\n  .navbar-form .input-group > .form-control {\n    width: 100%;\n  }\n  .navbar-form .control-label {\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .navbar-form .radio,\n  .navbar-form .checkbox {\n    display: inline-block;\n    margin-top: 0;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .navbar-form .radio label,\n  .navbar-form .checkbox label {\n    padding-left: 0;\n  }\n  .navbar-form .radio input[type=\"radio\"],\n  .navbar-form .checkbox input[type=\"checkbox\"] {\n    position: relative;\n    margin-left: 0;\n  }\n  .navbar-form .has-feedback .form-control-feedback {\n    top: 0;\n  }\n}\n@media (max-width: 767px) {\n  .navbar-form .form-group {\n    margin-bottom: 5px;\n  }\n  .navbar-form .form-group:last-child {\n    margin-bottom: 0;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-form {\n    width: auto;\n    padding-top: 0;\n    padding-bottom: 0;\n    margin-right: 0;\n    margin-left: 0;\n    border: 0;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n  }\n}\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  margin-bottom: 0;\n  border-top-left-radius: 4px;\n  border-top-right-radius: 4px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n.navbar-btn {\n  margin-top: 8px;\n  margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n  margin-top: 14px;\n  margin-bottom: 14px;\n}\n.navbar-text {\n  margin-top: 15px;\n  margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n  .navbar-text {\n    float: left;\n    margin-right: 15px;\n    margin-left: 15px;\n  }\n}\n@media (min-width: 768px) {\n  .navbar-left {\n    float: left !important;\n  }\n  .navbar-right {\n    float: right !important;\n    margin-right: -15px;\n  }\n  .navbar-right ~ .navbar-right {\n    margin-right: 0;\n  }\n}\n.navbar-default {\n  background-color: #f8f8f8;\n  border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n  color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n  color: #5e5e5e;\n  background-color: transparent;\n}\n.navbar-default .navbar-text {\n  color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n  color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n  color: #333;\n  background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n  color: #555;\n  background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n  color: #ccc;\n  background-color: transparent;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n  color: #555;\n  background-color: #e7e7e7;\n}\n@media (max-width: 767px) {\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n    color: #777;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #333;\n    background-color: transparent;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #555;\n    background-color: #e7e7e7;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #ccc;\n    background-color: transparent;\n  }\n}\n.navbar-default .navbar-toggle {\n  border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n  background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n  background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n  border-color: #e7e7e7;\n}\n.navbar-default .navbar-link {\n  color: #777;\n}\n.navbar-default .navbar-link:hover {\n  color: #333;\n}\n.navbar-default .btn-link {\n  color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n  color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n  color: #ccc;\n}\n.navbar-inverse {\n  background-color: #222;\n  border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n  color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n  color: #fff;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n  color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n  color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n  color: #fff;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n  color: #fff;\n  background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n  color: #444;\n  background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n  color: #fff;\n  background-color: #080808;\n}\n@media (max-width: 767px) {\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n    border-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n    background-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n    color: #9d9d9d;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #fff;\n    background-color: transparent;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #fff;\n    background-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #444;\n    background-color: transparent;\n  }\n}\n.navbar-inverse .navbar-toggle {\n  border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n  background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n  background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n  border-color: #101010;\n}\n.navbar-inverse .navbar-link {\n  color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n  color: #fff;\n}\n.navbar-inverse .btn-link {\n  color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n  color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n  color: #444;\n}\n.breadcrumb {\n  padding: 8px 15px;\n  margin-bottom: 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  border-radius: 4px;\n}\n.breadcrumb > li {\n  display: inline-block;\n}\n.breadcrumb > li + li:before {\n  padding: 0 5px;\n  color: #ccc;\n  content: \"/\\00a0\";\n}\n.breadcrumb > .active {\n  color: #777777;\n}\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: 20px 0;\n  border-radius: 4px;\n}\n.pagination > li {\n  display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n  position: relative;\n  float: left;\n  padding: 6px 12px;\n  margin-left: -1px;\n  line-height: 1.42857143;\n  color: #337ab7;\n  text-decoration: none;\n  background-color: #fff;\n  border: 1px solid #ddd;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n  z-index: 2;\n  color: #23527c;\n  background-color: #eeeeee;\n  border-color: #ddd;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n  margin-left: 0;\n  border-top-left-radius: 4px;\n  border-bottom-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n  border-top-right-radius: 4px;\n  border-bottom-right-radius: 4px;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n  z-index: 3;\n  color: #fff;\n  cursor: default;\n  background-color: #337ab7;\n  border-color: #337ab7;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n  color: #777777;\n  cursor: not-allowed;\n  background-color: #fff;\n  border-color: #ddd;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n  border-top-left-radius: 6px;\n  border-bottom-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n  border-top-right-radius: 6px;\n  border-bottom-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n  border-top-left-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n  border-top-right-radius: 3px;\n  border-bottom-right-radius: 3px;\n}\n.pager {\n  padding-left: 0;\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n}\n.pager li {\n  display: inline;\n}\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n  color: #777777;\n  cursor: not-allowed;\n  background-color: #fff;\n}\n.label {\n  display: inline;\n  padding: 0.2em 0.6em 0.3em;\n  font-size: 75%;\n  font-weight: 700;\n  line-height: 1;\n  color: #fff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: 0.25em;\n}\na.label:hover,\na.label:focus {\n  color: #fff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.label:empty {\n  display: none;\n}\n.btn .label {\n  position: relative;\n  top: -1px;\n}\n.label-default {\n  background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n  background-color: #5e5e5e;\n}\n.label-primary {\n  background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n  background-color: #286090;\n}\n.label-success {\n  background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n  background-color: #449d44;\n}\n.label-info {\n  background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n  background-color: #31b0d5;\n}\n.label-warning {\n  background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n  background-color: #ec971f;\n}\n.label-danger {\n  background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n  background-color: #c9302c;\n}\n.badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: 12px;\n  font-weight: bold;\n  line-height: 1;\n  color: #fff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  background-color: #777777;\n  border-radius: 10px;\n}\n.badge:empty {\n  display: none;\n}\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n  top: 0;\n  padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n  color: #fff;\n  text-decoration: none;\n  cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: #337ab7;\n  background-color: #fff;\n}\n.list-group-item > .badge {\n  float: right;\n}\n.list-group-item > .badge + .badge {\n  margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\n.jumbotron {\n  padding-top: 30px;\n  padding-bottom: 30px;\n  margin-bottom: 30px;\n  color: inherit;\n  background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n  color: inherit;\n}\n.jumbotron p {\n  margin-bottom: 15px;\n  font-size: 21px;\n  font-weight: 200;\n}\n.jumbotron > hr {\n  border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n  padding-right: 15px;\n  padding-left: 15px;\n  border-radius: 6px;\n}\n.jumbotron .container {\n  max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n  .jumbotron {\n    padding-top: 48px;\n    padding-bottom: 48px;\n  }\n  .container .jumbotron,\n  .container-fluid .jumbotron {\n    padding-right: 60px;\n    padding-left: 60px;\n  }\n  .jumbotron h1,\n  .jumbotron .h1 {\n    font-size: 63px;\n  }\n}\n.thumbnail {\n  display: block;\n  padding: 4px;\n  margin-bottom: 20px;\n  line-height: 1.42857143;\n  background-color: #fff;\n  border: 1px solid #ddd;\n  border-radius: 4px;\n  -webkit-transition: border 0.2s ease-in-out;\n  -o-transition: border 0.2s ease-in-out;\n  transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n  margin-right: auto;\n  margin-left: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n  border-color: #337ab7;\n}\n.thumbnail .caption {\n  padding: 9px;\n  color: #333333;\n}\n.alert {\n  padding: 15px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n.alert h4 {\n  margin-top: 0;\n  color: inherit;\n}\n.alert .alert-link {\n  font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n  margin-bottom: 0;\n}\n.alert > p + p {\n  margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n  padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  color: inherit;\n}\n.alert-success {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n.alert-success hr {\n  border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n  color: #2b542c;\n}\n.alert-info {\n  color: #31708f;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n.alert-info hr {\n  border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n  color: #245269;\n}\n.alert-warning {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n.alert-warning hr {\n  border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n  color: #66512c;\n}\n.alert-danger {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n.alert-danger hr {\n  border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n  color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f5f5f5;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n  float: left;\n  width: 0%;\n  height: 100%;\n  font-size: 12px;\n  line-height: 20px;\n  color: #fff;\n  text-align: center;\n  background-color: #337ab7;\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-transition: width 0.6s ease;\n  -o-transition: width 0.6s ease;\n  transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  -webkit-background-size: 40px 40px;\n  background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n  -o-animation: progress-bar-stripes 2s linear infinite;\n  animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n  background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n  background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n  background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n  background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n  margin-top: 15px;\n}\n.media:first-child {\n  margin-top: 0;\n}\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n.media-body {\n  width: 10000px;\n}\n.media-object {\n  display: block;\n}\n.media-object.img-thumbnail {\n  max-width: none;\n}\n.media-right,\n.media > .pull-right {\n  padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n  padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n  display: table-cell;\n  vertical-align: top;\n}\n.media-middle {\n  vertical-align: middle;\n}\n.media-bottom {\n  vertical-align: bottom;\n}\n.media-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n.list-group {\n  padding-left: 0;\n  margin-bottom: 20px;\n}\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  margin-bottom: -1px;\n  background-color: #fff;\n  border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n  border-top-left-radius: 4px;\n  border-top-right-radius: 4px;\n}\n.list-group-item:last-child {\n  margin-bottom: 0;\n  border-bottom-right-radius: 4px;\n  border-bottom-left-radius: 4px;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n  color: #777777;\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n  color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n  color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n  z-index: 2;\n  color: #fff;\n  background-color: #337ab7;\n  border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n  color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n  color: #c7ddef;\n}\na.list-group-item,\nbutton.list-group-item {\n  color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n  color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n  color: #555;\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\nbutton.list-group-item {\n  width: 100%;\n  text-align: left;\n}\n.list-group-item-success {\n  color: #3c763d;\n  background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n  color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n  color: #3c763d;\n  background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n  color: #fff;\n  background-color: #3c763d;\n  border-color: #3c763d;\n}\n.list-group-item-info {\n  color: #31708f;\n  background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n  color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n  color: #31708f;\n  background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n  color: #fff;\n  background-color: #31708f;\n  border-color: #31708f;\n}\n.list-group-item-warning {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n  color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n  color: #8a6d3b;\n  background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n  color: #fff;\n  background-color: #8a6d3b;\n  border-color: #8a6d3b;\n}\n.list-group-item-danger {\n  color: #a94442;\n  background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n  color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n  color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n  color: #a94442;\n  background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n  color: #fff;\n  background-color: #a94442;\n  border-color: #a94442;\n}\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n.panel {\n  margin-bottom: 20px;\n  background-color: #fff;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n  padding: 15px;\n}\n.panel-heading {\n  padding: 10px 15px;\n  border-bottom: 1px solid transparent;\n  border-top-left-radius: 3px;\n  border-top-right-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n  color: inherit;\n}\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 16px;\n  color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n  color: inherit;\n}\n.panel-footer {\n  padding: 10px 15px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #ddd;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n  margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n  border-width: 1px 0;\n  border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n  border-top: 0;\n  border-top-left-radius: 3px;\n  border-top-right-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n  border-bottom: 0;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n  border-top-left-radius: 0;\n  border-top-right-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n  border-top-width: 0;\n}\n.list-group + .panel-footer {\n  border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n  margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n  padding-right: 15px;\n  padding-left: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n  border-top-left-radius: 3px;\n  border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n  border-top-left-radius: 3px;\n  border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n  border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n  border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n  border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n  border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n  border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n  border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n  border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n  border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n  border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n  border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n  border-bottom: 0;\n}\n.panel > .table-responsive {\n  margin-bottom: 0;\n  border: 0;\n}\n.panel-group {\n  margin-bottom: 20px;\n}\n.panel-group .panel {\n  margin-bottom: 0;\n  border-radius: 4px;\n}\n.panel-group .panel + .panel {\n  margin-top: 5px;\n}\n.panel-group .panel-heading {\n  border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n  border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n  border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n  border-bottom: 1px solid #ddd;\n}\n.panel-default {\n  border-color: #ddd;\n}\n.panel-default > .panel-heading {\n  color: #333333;\n  background-color: #f5f5f5;\n  border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n  border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n  color: #f5f5f5;\n  background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n  border-bottom-color: #ddd;\n}\n.panel-primary {\n  border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n  color: #fff;\n  background-color: #337ab7;\n  border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n  border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n  color: #337ab7;\n  background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n  border-bottom-color: #337ab7;\n}\n.panel-success {\n  border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n  color: #3c763d;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n  border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n  color: #dff0d8;\n  background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n  border-bottom-color: #d6e9c6;\n}\n.panel-info {\n  border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n  color: #31708f;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n  border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n  color: #d9edf7;\n  background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n  border-bottom-color: #bce8f1;\n}\n.panel-warning {\n  border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n  color: #8a6d3b;\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n  border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n  color: #fcf8e3;\n  background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n  border-bottom-color: #faebcc;\n}\n.panel-danger {\n  border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n  color: #a94442;\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n  border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n  color: #f2dede;\n  background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n  border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n  position: relative;\n  display: block;\n  height: 0;\n  padding: 0;\n  overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  border: 0;\n}\n.embed-responsive-16by9 {\n  padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n  padding-bottom: 75%;\n}\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n  padding: 24px;\n  border-radius: 6px;\n}\n.well-sm {\n  padding: 9px;\n  border-radius: 3px;\n}\n.close {\n  float: right;\n  font-size: 21px;\n  font-weight: bold;\n  line-height: 1;\n  color: #000;\n  text-shadow: 0 1px 0 #fff;\n  filter: alpha(opacity=20);\n  opacity: 0.2;\n}\n.close:hover,\n.close:focus {\n  color: #000;\n  text-decoration: none;\n  cursor: pointer;\n  filter: alpha(opacity=50);\n  opacity: 0.5;\n}\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n  -moz-appearance: none;\n  appearance: none;\n}\n.modal-open {\n  overflow: hidden;\n}\n.modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1050;\n  display: none;\n  overflow: hidden;\n  -webkit-overflow-scrolling: touch;\n  outline: 0;\n}\n.modal.fade .modal-dialog {\n  -webkit-transform: translate(0, -25%);\n  -ms-transform: translate(0, -25%);\n  -o-transform: translate(0, -25%);\n  transform: translate(0, -25%);\n  -webkit-transition: -webkit-transform 0.3s ease-out;\n  -o-transition: -o-transform 0.3s ease-out;\n  transition: -webkit-transform 0.3s ease-out;\n  transition: transform 0.3s ease-out;\n  transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out, -o-transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n  -webkit-transform: translate(0, 0);\n  -ms-transform: translate(0, 0);\n  -o-transform: translate(0, 0);\n  transform: translate(0, 0);\n}\n.modal-open .modal {\n  overflow-x: hidden;\n  overflow-y: auto;\n}\n.modal-dialog {\n  position: relative;\n  width: auto;\n  margin: 10px;\n}\n.modal-content {\n  position: relative;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid #999;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n  box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n  outline: 0;\n}\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  background-color: #000;\n}\n.modal-backdrop.fade {\n  filter: alpha(opacity=0);\n  opacity: 0;\n}\n.modal-backdrop.in {\n  filter: alpha(opacity=50);\n  opacity: 0.5;\n}\n.modal-header {\n  padding: 15px;\n  border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n  margin-top: -2px;\n}\n.modal-title {\n  margin: 0;\n  line-height: 1.42857143;\n}\n.modal-body {\n  position: relative;\n  padding: 15px;\n}\n.modal-footer {\n  padding: 15px;\n  text-align: right;\n  border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n.modal-scrollbar-measure {\n  position: absolute;\n  top: -9999px;\n  width: 50px;\n  height: 50px;\n  overflow: scroll;\n}\n@media (min-width: 768px) {\n  .modal-dialog {\n    width: 600px;\n    margin: 30px auto;\n  }\n  .modal-content {\n    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n  }\n  .modal-sm {\n    width: 300px;\n  }\n}\n@media (min-width: 992px) {\n  .modal-lg {\n    width: 900px;\n  }\n}\n.tooltip {\n  position: absolute;\n  z-index: 1070;\n  display: block;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-style: normal;\n  font-weight: 400;\n  line-height: 1.42857143;\n  line-break: auto;\n  text-align: left;\n  text-align: start;\n  text-decoration: none;\n  text-shadow: none;\n  text-transform: none;\n  letter-spacing: normal;\n  word-break: normal;\n  word-spacing: normal;\n  word-wrap: normal;\n  white-space: normal;\n  font-size: 12px;\n  filter: alpha(opacity=0);\n  opacity: 0;\n}\n.tooltip.in {\n  filter: alpha(opacity=90);\n  opacity: 0.9;\n}\n.tooltip.top {\n  padding: 5px 0;\n  margin-top: -3px;\n}\n.tooltip.right {\n  padding: 0 5px;\n  margin-left: 3px;\n}\n.tooltip.bottom {\n  padding: 5px 0;\n  margin-top: 3px;\n}\n.tooltip.left {\n  padding: 0 5px;\n  margin-left: -3px;\n}\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-width: 5px 5px 0;\n  border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n  right: 5px;\n  bottom: 0;\n  margin-bottom: -5px;\n  border-width: 5px 5px 0;\n  border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n  bottom: 0;\n  left: 5px;\n  margin-bottom: -5px;\n  border-width: 5px 5px 0;\n  border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-width: 5px 5px 5px 0;\n  border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-width: 5px 0 5px 5px;\n  border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n  top: 0;\n  right: 5px;\n  margin-top: -5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n  top: 0;\n  left: 5px;\n  margin-top: -5px;\n  border-width: 0 5px 5px;\n  border-bottom-color: #000;\n}\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #fff;\n  text-align: center;\n  background-color: #000;\n  border-radius: 4px;\n}\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1060;\n  display: none;\n  max-width: 276px;\n  padding: 1px;\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-style: normal;\n  font-weight: 400;\n  line-height: 1.42857143;\n  line-break: auto;\n  text-align: left;\n  text-align: start;\n  text-decoration: none;\n  text-shadow: none;\n  text-transform: none;\n  letter-spacing: normal;\n  word-break: normal;\n  word-spacing: normal;\n  word-wrap: normal;\n  white-space: normal;\n  font-size: 14px;\n  background-color: #fff;\n  background-clip: padding-box;\n  border: 1px solid #ccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n  margin-top: -10px;\n}\n.popover.right {\n  margin-left: 10px;\n}\n.popover.bottom {\n  margin-top: 10px;\n}\n.popover.left {\n  margin-left: -10px;\n}\n.popover > .arrow {\n  border-width: 11px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n.popover > .arrow:after {\n  content: \"\";\n  border-width: 10px;\n}\n.popover.top > .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n.popover.top > .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  content: \" \";\n  border-top-color: #fff;\n  border-bottom-width: 0;\n}\n.popover.right > .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n.popover.right > .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  content: \" \";\n  border-right-color: #fff;\n  border-left-width: 0;\n}\n.popover.bottom > .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-width: 0;\n  border-bottom-color: #999999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n.popover.bottom > .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  content: \" \";\n  border-top-width: 0;\n  border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-right-width: 0;\n  border-left-color: #999999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  content: \" \";\n  border-right-width: 0;\n  border-left-color: #fff;\n}\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  border-radius: 5px 5px 0 0;\n}\n.popover-content {\n  padding: 9px 14px;\n}\n.carousel {\n  position: relative;\n}\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n  -o-transition: 0.6s ease-in-out left;\n  transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n  .carousel-inner > .item {\n    -webkit-transition: -webkit-transform 0.6s ease-in-out;\n    -o-transition: -o-transform 0.6s ease-in-out;\n    transition: -webkit-transform 0.6s ease-in-out;\n    transition: transform 0.6s ease-in-out;\n    transition: transform 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out, -o-transform 0.6s ease-in-out;\n    -webkit-backface-visibility: hidden;\n    backface-visibility: hidden;\n    -webkit-perspective: 1000px;\n    perspective: 1000px;\n  }\n  .carousel-inner > .item.next,\n  .carousel-inner > .item.active.right {\n    -webkit-transform: translate3d(100%, 0, 0);\n    transform: translate3d(100%, 0, 0);\n    left: 0;\n  }\n  .carousel-inner > .item.prev,\n  .carousel-inner > .item.active.left {\n    -webkit-transform: translate3d(-100%, 0, 0);\n    transform: translate3d(-100%, 0, 0);\n    left: 0;\n  }\n  .carousel-inner > .item.next.left,\n  .carousel-inner > .item.prev.right,\n  .carousel-inner > .item.active {\n    -webkit-transform: translate3d(0, 0, 0);\n    transform: translate3d(0, 0, 0);\n    left: 0;\n  }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n.carousel-inner > .active {\n  left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n.carousel-inner > .next {\n  left: 100%;\n}\n.carousel-inner > .prev {\n  left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n.carousel-inner > .active.left {\n  left: -100%;\n}\n.carousel-inner > .active.right {\n  left: 100%;\n}\n.carousel-control {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  width: 15%;\n  font-size: 20px;\n  color: #fff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n  background-color: rgba(0, 0, 0, 0);\n  filter: alpha(opacity=50);\n  opacity: 0.5;\n}\n.carousel-control.left {\n  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n  background-repeat: repeat-x;\n}\n.carousel-control.right {\n  right: 0;\n  left: auto;\n  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n  background-repeat: repeat-x;\n}\n.carousel-control:hover,\n.carousel-control:focus {\n  color: #fff;\n  text-decoration: none;\n  outline: 0;\n  filter: alpha(opacity=90);\n  opacity: 0.9;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n  position: absolute;\n  top: 50%;\n  z-index: 5;\n  display: inline-block;\n  margin-top: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n  left: 50%;\n  margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n  right: 50%;\n  margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n  width: 20px;\n  height: 20px;\n  font-family: serif;\n  line-height: 1;\n}\n.carousel-control .icon-prev:before {\n  content: \"\\2039\";\n}\n.carousel-control .icon-next:before {\n  content: \"\\203a\";\n}\n.carousel-indicators {\n  position: absolute;\n  bottom: 10px;\n  left: 50%;\n  z-index: 15;\n  width: 60%;\n  padding-left: 0;\n  margin-left: -30%;\n  text-align: center;\n  list-style: none;\n}\n.carousel-indicators li {\n  display: inline-block;\n  width: 10px;\n  height: 10px;\n  margin: 1px;\n  text-indent: -999px;\n  cursor: pointer;\n  background-color: #000 \\9;\n  background-color: rgba(0, 0, 0, 0);\n  border: 1px solid #fff;\n  border-radius: 10px;\n}\n.carousel-indicators .active {\n  width: 12px;\n  height: 12px;\n  margin: 0;\n  background-color: #fff;\n}\n.carousel-caption {\n  position: absolute;\n  right: 15%;\n  bottom: 20px;\n  left: 15%;\n  z-index: 10;\n  padding-top: 20px;\n  padding-bottom: 20px;\n  color: #fff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n  text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n  .carousel-control .glyphicon-chevron-left,\n  .carousel-control .glyphicon-chevron-right,\n  .carousel-control .icon-prev,\n  .carousel-control .icon-next {\n    width: 30px;\n    height: 30px;\n    margin-top: -10px;\n    font-size: 30px;\n  }\n  .carousel-control .glyphicon-chevron-left,\n  .carousel-control .icon-prev {\n    margin-left: -10px;\n  }\n  .carousel-control .glyphicon-chevron-right,\n  .carousel-control .icon-next {\n    margin-right: -10px;\n  }\n  .carousel-caption {\n    right: 20%;\n    left: 20%;\n    padding-bottom: 30px;\n  }\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n  clear: both;\n}\n.center-block {\n  display: block;\n  margin-right: auto;\n  margin-left: auto;\n}\n.pull-right {\n  float: right !important;\n}\n.pull-left {\n  float: left !important;\n}\n.hide {\n  display: none !important;\n}\n.show {\n  display: block !important;\n}\n.invisible {\n  visibility: hidden;\n}\n.text-hide {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n.hidden {\n  display: none !important;\n}\n.affix {\n  position: fixed;\n}\n@-ms-viewport {\n  width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n  display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n  display: none !important;\n}\n@media (max-width: 767px) {\n  .visible-xs {\n    display: block !important;\n  }\n  table.visible-xs {\n    display: table !important;\n  }\n  tr.visible-xs {\n    display: table-row !important;\n  }\n  th.visible-xs,\n  td.visible-xs {\n    display: table-cell !important;\n  }\n}\n@media (max-width: 767px) {\n  .visible-xs-block {\n    display: block !important;\n  }\n}\n@media (max-width: 767px) {\n  .visible-xs-inline {\n    display: inline !important;\n  }\n}\n@media (max-width: 767px) {\n  .visible-xs-inline-block {\n    display: inline-block !important;\n  }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-sm {\n    display: block !important;\n  }\n  table.visible-sm {\n    display: table !important;\n  }\n  tr.visible-sm {\n    display: table-row !important;\n  }\n  th.visible-sm,\n  td.visible-sm {\n    display: table-cell !important;\n  }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-sm-block {\n    display: block !important;\n  }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-sm-inline {\n    display: inline !important;\n  }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-sm-inline-block {\n    display: inline-block !important;\n  }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-md {\n    display: block !important;\n  }\n  table.visible-md {\n    display: table !important;\n  }\n  tr.visible-md {\n    display: table-row !important;\n  }\n  th.visible-md,\n  td.visible-md {\n    display: table-cell !important;\n  }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-md-block {\n    display: block !important;\n  }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-md-inline {\n    display: inline !important;\n  }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-md-inline-block {\n    display: inline-block !important;\n  }\n}\n@media (min-width: 1200px) {\n  .visible-lg {\n    display: block !important;\n  }\n  table.visible-lg {\n    display: table !important;\n  }\n  tr.visible-lg {\n    display: table-row !important;\n  }\n  th.visible-lg,\n  td.visible-lg {\n    display: table-cell !important;\n  }\n}\n@media (min-width: 1200px) {\n  .visible-lg-block {\n    display: block !important;\n  }\n}\n@media (min-width: 1200px) {\n  .visible-lg-inline {\n    display: inline !important;\n  }\n}\n@media (min-width: 1200px) {\n  .visible-lg-inline-block {\n    display: inline-block !important;\n  }\n}\n@media (max-width: 767px) {\n  .hidden-xs {\n    display: none !important;\n  }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-sm {\n    display: none !important;\n  }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-md {\n    display: none !important;\n  }\n}\n@media (min-width: 1200px) {\n  .hidden-lg {\n    display: none !important;\n  }\n}\n.visible-print {\n  display: none !important;\n}\n@media print {\n  .visible-print {\n    display: block !important;\n  }\n  table.visible-print {\n    display: table !important;\n  }\n  tr.visible-print {\n    display: table-row !important;\n  }\n  th.visible-print,\n  td.visible-print {\n    display: table-cell !important;\n  }\n}\n.visible-print-block {\n  display: none !important;\n}\n@media print {\n  .visible-print-block {\n    display: block !important;\n  }\n}\n.visible-print-inline {\n  display: none !important;\n}\n@media print {\n  .visible-print-inline {\n    display: inline !important;\n  }\n}\n.visible-print-inline-block {\n  display: none !important;\n}\n@media print {\n  .visible-print-inline-block {\n    display: inline-block !important;\n  }\n}\n@media print {\n  .hidden-print {\n    display: none !important;\n  }\n}\n/*# sourceMappingURL=bootstrap.css.map */"
  },
  {
    "path": "ad/NHA/files/wwwroot/Global.asax",
    "content": "﻿<%@ Application Codebehind=\"Global.asax.cs\" Inherits=\"adrutro.MvcApplication\" Language=\"C#\" %>\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Models/AcademyModel.edmx.diagram",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<edmx:Edmx Version=\"3.0\" xmlns:edmx=\"http://schemas.microsoft.com/ado/2009/11/edmx\">\r\n <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) -->\r\n  <edmx:Designer xmlns=\"http://schemas.microsoft.com/ado/2009/11/edmx\">\r\n    <!-- Diagram content (shape and connector positions) -->\r\n    <edmx:Diagrams>\r\n      <Diagram DiagramId=\"2c665392ee8e4511b477a4662de8f2b6\" Name=\"Diagram1\">\r\n        <EntityTypeShape EntityType=\"academyModel.Student\" Width=\"1.5\" PointX=\"0.75\" PointY=\"0.75\" IsExpanded=\"true\" />\r\n      </Diagram>\r\n    </edmx:Diagrams>\r\n  </edmx:Designer>\r\n</edmx:Edmx>"
  },
  {
    "path": "ad/NHA/files/wwwroot/Scripts/bootstrap.js",
    "content": "/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under the MIT license\n */\n\nif (typeof jQuery === 'undefined') {\n  throw new Error('Bootstrap\\'s JavaScript requires jQuery')\n}\n\n+function ($) {\n  'use strict';\n  var version = $.fn.jquery.split(' ')[0].split('.')\n  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {\n    throw new Error('Bootstrap\\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')\n  }\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: transition.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#transitions\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // CSS TRANSITION SUPPORT (Shoutout: https://modernizr.com/)\n  // ============================================================\n\n  function transitionEnd() {\n    var el = document.createElement('bootstrap')\n\n    var transEndEventNames = {\n      WebkitTransition : 'webkitTransitionEnd',\n      MozTransition    : 'transitionend',\n      OTransition      : 'oTransitionEnd otransitionend',\n      transition       : 'transitionend'\n    }\n\n    for (var name in transEndEventNames) {\n      if (el.style[name] !== undefined) {\n        return { end: transEndEventNames[name] }\n      }\n    }\n\n    return false // explicit for ie8 (  ._.)\n  }\n\n  // https://blog.alexmaccaw.com/css-transitions\n  $.fn.emulateTransitionEnd = function (duration) {\n    var called = false\n    var $el = this\n    $(this).one('bsTransitionEnd', function () { called = true })\n    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }\n    setTimeout(callback, duration)\n    return this\n  }\n\n  $(function () {\n    $.support.transition = transitionEnd()\n\n    if (!$.support.transition) return\n\n    $.event.special.bsTransitionEnd = {\n      bindType: $.support.transition.end,\n      delegateType: $.support.transition.end,\n      handle: function (e) {\n        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)\n      }\n    }\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: alert.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#alerts\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // ALERT CLASS DEFINITION\n  // ======================\n\n  var dismiss = '[data-dismiss=\"alert\"]'\n  var Alert   = function (el) {\n    $(el).on('click', dismiss, this.close)\n  }\n\n  Alert.VERSION = '3.4.1'\n\n  Alert.TRANSITION_DURATION = 150\n\n  Alert.prototype.close = function (e) {\n    var $this    = $(this)\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    selector    = selector === '#' ? [] : selector\n    var $parent = $(document).find(selector)\n\n    if (e) e.preventDefault()\n\n    if (!$parent.length) {\n      $parent = $this.closest('.alert')\n    }\n\n    $parent.trigger(e = $.Event('close.bs.alert'))\n\n    if (e.isDefaultPrevented()) return\n\n    $parent.removeClass('in')\n\n    function removeElement() {\n      // detach from parent, fire event then clean up data\n      $parent.detach().trigger('closed.bs.alert').remove()\n    }\n\n    $.support.transition && $parent.hasClass('fade') ?\n      $parent\n        .one('bsTransitionEnd', removeElement)\n        .emulateTransitionEnd(Alert.TRANSITION_DURATION) :\n      removeElement()\n  }\n\n\n  // ALERT PLUGIN DEFINITION\n  // =======================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.alert')\n\n      if (!data) $this.data('bs.alert', (data = new Alert(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  var old = $.fn.alert\n\n  $.fn.alert             = Plugin\n  $.fn.alert.Constructor = Alert\n\n\n  // ALERT NO CONFLICT\n  // =================\n\n  $.fn.alert.noConflict = function () {\n    $.fn.alert = old\n    return this\n  }\n\n\n  // ALERT DATA-API\n  // ==============\n\n  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: button.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#buttons\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // BUTTON PUBLIC CLASS DEFINITION\n  // ==============================\n\n  var Button = function (element, options) {\n    this.$element  = $(element)\n    this.options   = $.extend({}, Button.DEFAULTS, options)\n    this.isLoading = false\n  }\n\n  Button.VERSION  = '3.4.1'\n\n  Button.DEFAULTS = {\n    loadingText: 'loading...'\n  }\n\n  Button.prototype.setState = function (state) {\n    var d    = 'disabled'\n    var $el  = this.$element\n    var val  = $el.is('input') ? 'val' : 'html'\n    var data = $el.data()\n\n    state += 'Text'\n\n    if (data.resetText == null) $el.data('resetText', $el[val]())\n\n    // push to event loop to allow forms to submit\n    setTimeout($.proxy(function () {\n      $el[val](data[state] == null ? this.options[state] : data[state])\n\n      if (state == 'loadingText') {\n        this.isLoading = true\n        $el.addClass(d).attr(d, d).prop(d, true)\n      } else if (this.isLoading) {\n        this.isLoading = false\n        $el.removeClass(d).removeAttr(d).prop(d, false)\n      }\n    }, this), 0)\n  }\n\n  Button.prototype.toggle = function () {\n    var changed = true\n    var $parent = this.$element.closest('[data-toggle=\"buttons\"]')\n\n    if ($parent.length) {\n      var $input = this.$element.find('input')\n      if ($input.prop('type') == 'radio') {\n        if ($input.prop('checked')) changed = false\n        $parent.find('.active').removeClass('active')\n        this.$element.addClass('active')\n      } else if ($input.prop('type') == 'checkbox') {\n        if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false\n        this.$element.toggleClass('active')\n      }\n      $input.prop('checked', this.$element.hasClass('active'))\n      if (changed) $input.trigger('change')\n    } else {\n      this.$element.attr('aria-pressed', !this.$element.hasClass('active'))\n      this.$element.toggleClass('active')\n    }\n  }\n\n\n  // BUTTON PLUGIN DEFINITION\n  // ========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.button')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.button', (data = new Button(this, options)))\n\n      if (option == 'toggle') data.toggle()\n      else if (option) data.setState(option)\n    })\n  }\n\n  var old = $.fn.button\n\n  $.fn.button             = Plugin\n  $.fn.button.Constructor = Button\n\n\n  // BUTTON NO CONFLICT\n  // ==================\n\n  $.fn.button.noConflict = function () {\n    $.fn.button = old\n    return this\n  }\n\n\n  // BUTTON DATA-API\n  // ===============\n\n  $(document)\n    .on('click.bs.button.data-api', '[data-toggle^=\"button\"]', function (e) {\n      var $btn = $(e.target).closest('.btn')\n      Plugin.call($btn, 'toggle')\n      if (!($(e.target).is('input[type=\"radio\"], input[type=\"checkbox\"]'))) {\n        // Prevent double click on radios, and the double selections (so cancellation) on checkboxes\n        e.preventDefault()\n        // The target component still receive the focus\n        if ($btn.is('input,button')) $btn.trigger('focus')\n        else $btn.find('input:visible,button:visible').first().trigger('focus')\n      }\n    })\n    .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^=\"button\"]', function (e) {\n      $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))\n    })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: carousel.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#carousel\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // CAROUSEL CLASS DEFINITION\n  // =========================\n\n  var Carousel = function (element, options) {\n    this.$element    = $(element)\n    this.$indicators = this.$element.find('.carousel-indicators')\n    this.options     = options\n    this.paused      = null\n    this.sliding     = null\n    this.interval    = null\n    this.$active     = null\n    this.$items      = null\n\n    this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))\n\n    this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element\n      .on('mouseenter.bs.carousel', $.proxy(this.pause, this))\n      .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))\n  }\n\n  Carousel.VERSION  = '3.4.1'\n\n  Carousel.TRANSITION_DURATION = 600\n\n  Carousel.DEFAULTS = {\n    interval: 5000,\n    pause: 'hover',\n    wrap: true,\n    keyboard: true\n  }\n\n  Carousel.prototype.keydown = function (e) {\n    if (/input|textarea/i.test(e.target.tagName)) return\n    switch (e.which) {\n      case 37: this.prev(); break\n      case 39: this.next(); break\n      default: return\n    }\n\n    e.preventDefault()\n  }\n\n  Carousel.prototype.cycle = function (e) {\n    e || (this.paused = false)\n\n    this.interval && clearInterval(this.interval)\n\n    this.options.interval\n      && !this.paused\n      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))\n\n    return this\n  }\n\n  Carousel.prototype.getItemIndex = function (item) {\n    this.$items = item.parent().children('.item')\n    return this.$items.index(item || this.$active)\n  }\n\n  Carousel.prototype.getItemForDirection = function (direction, active) {\n    var activeIndex = this.getItemIndex(active)\n    var willWrap = (direction == 'prev' && activeIndex === 0)\n                || (direction == 'next' && activeIndex == (this.$items.length - 1))\n    if (willWrap && !this.options.wrap) return active\n    var delta = direction == 'prev' ? -1 : 1\n    var itemIndex = (activeIndex + delta) % this.$items.length\n    return this.$items.eq(itemIndex)\n  }\n\n  Carousel.prototype.to = function (pos) {\n    var that        = this\n    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))\n\n    if (pos > (this.$items.length - 1) || pos < 0) return\n\n    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, \"slid\"\n    if (activeIndex == pos) return this.pause().cycle()\n\n    return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))\n  }\n\n  Carousel.prototype.pause = function (e) {\n    e || (this.paused = true)\n\n    if (this.$element.find('.next, .prev').length && $.support.transition) {\n      this.$element.trigger($.support.transition.end)\n      this.cycle(true)\n    }\n\n    this.interval = clearInterval(this.interval)\n\n    return this\n  }\n\n  Carousel.prototype.next = function () {\n    if (this.sliding) return\n    return this.slide('next')\n  }\n\n  Carousel.prototype.prev = function () {\n    if (this.sliding) return\n    return this.slide('prev')\n  }\n\n  Carousel.prototype.slide = function (type, next) {\n    var $active   = this.$element.find('.item.active')\n    var $next     = next || this.getItemForDirection(type, $active)\n    var isCycling = this.interval\n    var direction = type == 'next' ? 'left' : 'right'\n    var that      = this\n\n    if ($next.hasClass('active')) return (this.sliding = false)\n\n    var relatedTarget = $next[0]\n    var slideEvent = $.Event('slide.bs.carousel', {\n      relatedTarget: relatedTarget,\n      direction: direction\n    })\n    this.$element.trigger(slideEvent)\n    if (slideEvent.isDefaultPrevented()) return\n\n    this.sliding = true\n\n    isCycling && this.pause()\n\n    if (this.$indicators.length) {\n      this.$indicators.find('.active').removeClass('active')\n      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])\n      $nextIndicator && $nextIndicator.addClass('active')\n    }\n\n    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, \"slid\"\n    if ($.support.transition && this.$element.hasClass('slide')) {\n      $next.addClass(type)\n      if (typeof $next === 'object' && $next.length) {\n        $next[0].offsetWidth // force reflow\n      }\n      $active.addClass(direction)\n      $next.addClass(direction)\n      $active\n        .one('bsTransitionEnd', function () {\n          $next.removeClass([type, direction].join(' ')).addClass('active')\n          $active.removeClass(['active', direction].join(' '))\n          that.sliding = false\n          setTimeout(function () {\n            that.$element.trigger(slidEvent)\n          }, 0)\n        })\n        .emulateTransitionEnd(Carousel.TRANSITION_DURATION)\n    } else {\n      $active.removeClass('active')\n      $next.addClass('active')\n      this.sliding = false\n      this.$element.trigger(slidEvent)\n    }\n\n    isCycling && this.cycle()\n\n    return this\n  }\n\n\n  // CAROUSEL PLUGIN DEFINITION\n  // ==========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.carousel')\n      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)\n      var action  = typeof option == 'string' ? option : options.slide\n\n      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))\n      if (typeof option == 'number') data.to(option)\n      else if (action) data[action]()\n      else if (options.interval) data.pause().cycle()\n    })\n  }\n\n  var old = $.fn.carousel\n\n  $.fn.carousel             = Plugin\n  $.fn.carousel.Constructor = Carousel\n\n\n  // CAROUSEL NO CONFLICT\n  // ====================\n\n  $.fn.carousel.noConflict = function () {\n    $.fn.carousel = old\n    return this\n  }\n\n\n  // CAROUSEL DATA-API\n  // =================\n\n  var clickHandler = function (e) {\n    var $this   = $(this)\n    var href    = $this.attr('href')\n    if (href) {\n      href = href.replace(/.*(?=#[^\\s]+$)/, '') // strip for ie7\n    }\n\n    var target  = $this.attr('data-target') || href\n    var $target = $(document).find(target)\n\n    if (!$target.hasClass('carousel')) return\n\n    var options = $.extend({}, $target.data(), $this.data())\n    var slideIndex = $this.attr('data-slide-to')\n    if (slideIndex) options.interval = false\n\n    Plugin.call($target, options)\n\n    if (slideIndex) {\n      $target.data('bs.carousel').to(slideIndex)\n    }\n\n    e.preventDefault()\n  }\n\n  $(document)\n    .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)\n    .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)\n\n  $(window).on('load', function () {\n    $('[data-ride=\"carousel\"]').each(function () {\n      var $carousel = $(this)\n      Plugin.call($carousel, $carousel.data())\n    })\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: collapse.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#collapse\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n/* jshint latedef: false */\n\n+function ($) {\n  'use strict';\n\n  // COLLAPSE PUBLIC CLASS DEFINITION\n  // ================================\n\n  var Collapse = function (element, options) {\n    this.$element      = $(element)\n    this.options       = $.extend({}, Collapse.DEFAULTS, options)\n    this.$trigger      = $('[data-toggle=\"collapse\"][href=\"#' + element.id + '\"],' +\n                           '[data-toggle=\"collapse\"][data-target=\"#' + element.id + '\"]')\n    this.transitioning = null\n\n    if (this.options.parent) {\n      this.$parent = this.getParent()\n    } else {\n      this.addAriaAndCollapsedClass(this.$element, this.$trigger)\n    }\n\n    if (this.options.toggle) this.toggle()\n  }\n\n  Collapse.VERSION  = '3.4.1'\n\n  Collapse.TRANSITION_DURATION = 350\n\n  Collapse.DEFAULTS = {\n    toggle: true\n  }\n\n  Collapse.prototype.dimension = function () {\n    var hasWidth = this.$element.hasClass('width')\n    return hasWidth ? 'width' : 'height'\n  }\n\n  Collapse.prototype.show = function () {\n    if (this.transitioning || this.$element.hasClass('in')) return\n\n    var activesData\n    var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')\n\n    if (actives && actives.length) {\n      activesData = actives.data('bs.collapse')\n      if (activesData && activesData.transitioning) return\n    }\n\n    var startEvent = $.Event('show.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    if (actives && actives.length) {\n      Plugin.call(actives, 'hide')\n      activesData || actives.data('bs.collapse', null)\n    }\n\n    var dimension = this.dimension()\n\n    this.$element\n      .removeClass('collapse')\n      .addClass('collapsing')[dimension](0)\n      .attr('aria-expanded', true)\n\n    this.$trigger\n      .removeClass('collapsed')\n      .attr('aria-expanded', true)\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.$element\n        .removeClass('collapsing')\n        .addClass('collapse in')[dimension]('')\n      this.transitioning = 0\n      this.$element\n        .trigger('shown.bs.collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    var scrollSize = $.camelCase(['scroll', dimension].join('-'))\n\n    this.$element\n      .one('bsTransitionEnd', $.proxy(complete, this))\n      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])\n  }\n\n  Collapse.prototype.hide = function () {\n    if (this.transitioning || !this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('hide.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var dimension = this.dimension()\n\n    this.$element[dimension](this.$element[dimension]())[0].offsetHeight\n\n    this.$element\n      .addClass('collapsing')\n      .removeClass('collapse in')\n      .attr('aria-expanded', false)\n\n    this.$trigger\n      .addClass('collapsed')\n      .attr('aria-expanded', false)\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.transitioning = 0\n      this.$element\n        .removeClass('collapsing')\n        .addClass('collapse')\n        .trigger('hidden.bs.collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    this.$element\n      [dimension](0)\n      .one('bsTransitionEnd', $.proxy(complete, this))\n      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)\n  }\n\n  Collapse.prototype.toggle = function () {\n    this[this.$element.hasClass('in') ? 'hide' : 'show']()\n  }\n\n  Collapse.prototype.getParent = function () {\n    return $(document).find(this.options.parent)\n      .find('[data-toggle=\"collapse\"][data-parent=\"' + this.options.parent + '\"]')\n      .each($.proxy(function (i, element) {\n        var $element = $(element)\n        this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)\n      }, this))\n      .end()\n  }\n\n  Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {\n    var isOpen = $element.hasClass('in')\n\n    $element.attr('aria-expanded', isOpen)\n    $trigger\n      .toggleClass('collapsed', !isOpen)\n      .attr('aria-expanded', isOpen)\n  }\n\n  function getTargetFromTrigger($trigger) {\n    var href\n    var target = $trigger.attr('data-target')\n      || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '') // strip for ie7\n\n    return $(document).find(target)\n  }\n\n\n  // COLLAPSE PLUGIN DEFINITION\n  // ==========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.collapse')\n      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false\n      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.collapse\n\n  $.fn.collapse             = Plugin\n  $.fn.collapse.Constructor = Collapse\n\n\n  // COLLAPSE NO CONFLICT\n  // ====================\n\n  $.fn.collapse.noConflict = function () {\n    $.fn.collapse = old\n    return this\n  }\n\n\n  // COLLAPSE DATA-API\n  // =================\n\n  $(document).on('click.bs.collapse.data-api', '[data-toggle=\"collapse\"]', function (e) {\n    var $this   = $(this)\n\n    if (!$this.attr('data-target')) e.preventDefault()\n\n    var $target = getTargetFromTrigger($this)\n    var data    = $target.data('bs.collapse')\n    var option  = data ? 'toggle' : $this.data()\n\n    Plugin.call($target, option)\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: dropdown.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#dropdowns\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // DROPDOWN CLASS DEFINITION\n  // =========================\n\n  var backdrop = '.dropdown-backdrop'\n  var toggle   = '[data-toggle=\"dropdown\"]'\n  var Dropdown = function (element) {\n    $(element).on('click.bs.dropdown', this.toggle)\n  }\n\n  Dropdown.VERSION = '3.4.1'\n\n  function getParent($this) {\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    var $parent = selector !== '#' ? $(document).find(selector) : null\n\n    return $parent && $parent.length ? $parent : $this.parent()\n  }\n\n  function clearMenus(e) {\n    if (e && e.which === 3) return\n    $(backdrop).remove()\n    $(toggle).each(function () {\n      var $this         = $(this)\n      var $parent       = getParent($this)\n      var relatedTarget = { relatedTarget: this }\n\n      if (!$parent.hasClass('open')) return\n\n      if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return\n\n      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))\n\n      if (e.isDefaultPrevented()) return\n\n      $this.attr('aria-expanded', 'false')\n      $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))\n    })\n  }\n\n  Dropdown.prototype.toggle = function (e) {\n    var $this = $(this)\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    clearMenus()\n\n    if (!isActive) {\n      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {\n        // if mobile we use a backdrop because click events don't delegate\n        $(document.createElement('div'))\n          .addClass('dropdown-backdrop')\n          .insertAfter($(this))\n          .on('click', clearMenus)\n      }\n\n      var relatedTarget = { relatedTarget: this }\n      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))\n\n      if (e.isDefaultPrevented()) return\n\n      $this\n        .trigger('focus')\n        .attr('aria-expanded', 'true')\n\n      $parent\n        .toggleClass('open')\n        .trigger($.Event('shown.bs.dropdown', relatedTarget))\n    }\n\n    return false\n  }\n\n  Dropdown.prototype.keydown = function (e) {\n    if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return\n\n    var $this = $(this)\n\n    e.preventDefault()\n    e.stopPropagation()\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    if (!isActive && e.which != 27 || isActive && e.which == 27) {\n      if (e.which == 27) $parent.find(toggle).trigger('focus')\n      return $this.trigger('click')\n    }\n\n    var desc = ' li:not(.disabled):visible a'\n    var $items = $parent.find('.dropdown-menu' + desc)\n\n    if (!$items.length) return\n\n    var index = $items.index(e.target)\n\n    if (e.which == 38 && index > 0)                 index--         // up\n    if (e.which == 40 && index < $items.length - 1) index++         // down\n    if (!~index)                                    index = 0\n\n    $items.eq(index).trigger('focus')\n  }\n\n\n  // DROPDOWN PLUGIN DEFINITION\n  // ==========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.dropdown')\n\n      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  var old = $.fn.dropdown\n\n  $.fn.dropdown             = Plugin\n  $.fn.dropdown.Constructor = Dropdown\n\n\n  // DROPDOWN NO CONFLICT\n  // ====================\n\n  $.fn.dropdown.noConflict = function () {\n    $.fn.dropdown = old\n    return this\n  }\n\n\n  // APPLY TO STANDARD DROPDOWN ELEMENTS\n  // ===================================\n\n  $(document)\n    .on('click.bs.dropdown.data-api', clearMenus)\n    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })\n    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)\n    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)\n    .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: modal.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#modals\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // MODAL CLASS DEFINITION\n  // ======================\n\n  var Modal = function (element, options) {\n    this.options = options\n    this.$body = $(document.body)\n    this.$element = $(element)\n    this.$dialog = this.$element.find('.modal-dialog')\n    this.$backdrop = null\n    this.isShown = null\n    this.originalBodyPad = null\n    this.scrollbarWidth = 0\n    this.ignoreBackdropClick = false\n    this.fixedContent = '.navbar-fixed-top, .navbar-fixed-bottom'\n\n    if (this.options.remote) {\n      this.$element\n        .find('.modal-content')\n        .load(this.options.remote, $.proxy(function () {\n          this.$element.trigger('loaded.bs.modal')\n        }, this))\n    }\n  }\n\n  Modal.VERSION = '3.4.1'\n\n  Modal.TRANSITION_DURATION = 300\n  Modal.BACKDROP_TRANSITION_DURATION = 150\n\n  Modal.DEFAULTS = {\n    backdrop: true,\n    keyboard: true,\n    show: true\n  }\n\n  Modal.prototype.toggle = function (_relatedTarget) {\n    return this.isShown ? this.hide() : this.show(_relatedTarget)\n  }\n\n  Modal.prototype.show = function (_relatedTarget) {\n    var that = this\n    var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })\n\n    this.$element.trigger(e)\n\n    if (this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = true\n\n    this.checkScrollbar()\n    this.setScrollbar()\n    this.$body.addClass('modal-open')\n\n    this.escape()\n    this.resize()\n\n    this.$element.on('click.dismiss.bs.modal', '[data-dismiss=\"modal\"]', $.proxy(this.hide, this))\n\n    this.$dialog.on('mousedown.dismiss.bs.modal', function () {\n      that.$element.one('mouseup.dismiss.bs.modal', function (e) {\n        if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true\n      })\n    })\n\n    this.backdrop(function () {\n      var transition = $.support.transition && that.$element.hasClass('fade')\n\n      if (!that.$element.parent().length) {\n        that.$element.appendTo(that.$body) // don't move modals dom position\n      }\n\n      that.$element\n        .show()\n        .scrollTop(0)\n\n      that.adjustDialog()\n\n      if (transition) {\n        that.$element[0].offsetWidth // force reflow\n      }\n\n      that.$element.addClass('in')\n\n      that.enforceFocus()\n\n      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })\n\n      transition ?\n        that.$dialog // wait for modal to slide in\n          .one('bsTransitionEnd', function () {\n            that.$element.trigger('focus').trigger(e)\n          })\n          .emulateTransitionEnd(Modal.TRANSITION_DURATION) :\n        that.$element.trigger('focus').trigger(e)\n    })\n  }\n\n  Modal.prototype.hide = function (e) {\n    if (e) e.preventDefault()\n\n    e = $.Event('hide.bs.modal')\n\n    this.$element.trigger(e)\n\n    if (!this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = false\n\n    this.escape()\n    this.resize()\n\n    $(document).off('focusin.bs.modal')\n\n    this.$element\n      .removeClass('in')\n      .off('click.dismiss.bs.modal')\n      .off('mouseup.dismiss.bs.modal')\n\n    this.$dialog.off('mousedown.dismiss.bs.modal')\n\n    $.support.transition && this.$element.hasClass('fade') ?\n      this.$element\n        .one('bsTransitionEnd', $.proxy(this.hideModal, this))\n        .emulateTransitionEnd(Modal.TRANSITION_DURATION) :\n      this.hideModal()\n  }\n\n  Modal.prototype.enforceFocus = function () {\n    $(document)\n      .off('focusin.bs.modal') // guard against infinite focus loop\n      .on('focusin.bs.modal', $.proxy(function (e) {\n        if (document !== e.target &&\n          this.$element[0] !== e.target &&\n          !this.$element.has(e.target).length) {\n          this.$element.trigger('focus')\n        }\n      }, this))\n  }\n\n  Modal.prototype.escape = function () {\n    if (this.isShown && this.options.keyboard) {\n      this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {\n        e.which == 27 && this.hide()\n      }, this))\n    } else if (!this.isShown) {\n      this.$element.off('keydown.dismiss.bs.modal')\n    }\n  }\n\n  Modal.prototype.resize = function () {\n    if (this.isShown) {\n      $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))\n    } else {\n      $(window).off('resize.bs.modal')\n    }\n  }\n\n  Modal.prototype.hideModal = function () {\n    var that = this\n    this.$element.hide()\n    this.backdrop(function () {\n      that.$body.removeClass('modal-open')\n      that.resetAdjustments()\n      that.resetScrollbar()\n      that.$element.trigger('hidden.bs.modal')\n    })\n  }\n\n  Modal.prototype.removeBackdrop = function () {\n    this.$backdrop && this.$backdrop.remove()\n    this.$backdrop = null\n  }\n\n  Modal.prototype.backdrop = function (callback) {\n    var that = this\n    var animate = this.$element.hasClass('fade') ? 'fade' : ''\n\n    if (this.isShown && this.options.backdrop) {\n      var doAnimate = $.support.transition && animate\n\n      this.$backdrop = $(document.createElement('div'))\n        .addClass('modal-backdrop ' + animate)\n        .appendTo(this.$body)\n\n      this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {\n        if (this.ignoreBackdropClick) {\n          this.ignoreBackdropClick = false\n          return\n        }\n        if (e.target !== e.currentTarget) return\n        this.options.backdrop == 'static'\n          ? this.$element[0].focus()\n          : this.hide()\n      }, this))\n\n      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow\n\n      this.$backdrop.addClass('in')\n\n      if (!callback) return\n\n      doAnimate ?\n        this.$backdrop\n          .one('bsTransitionEnd', callback)\n          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :\n        callback()\n\n    } else if (!this.isShown && this.$backdrop) {\n      this.$backdrop.removeClass('in')\n\n      var callbackRemove = function () {\n        that.removeBackdrop()\n        callback && callback()\n      }\n      $.support.transition && this.$element.hasClass('fade') ?\n        this.$backdrop\n          .one('bsTransitionEnd', callbackRemove)\n          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :\n        callbackRemove()\n\n    } else if (callback) {\n      callback()\n    }\n  }\n\n  // these following methods are used to handle overflowing modals\n\n  Modal.prototype.handleUpdate = function () {\n    this.adjustDialog()\n  }\n\n  Modal.prototype.adjustDialog = function () {\n    var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight\n\n    this.$element.css({\n      paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',\n      paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''\n    })\n  }\n\n  Modal.prototype.resetAdjustments = function () {\n    this.$element.css({\n      paddingLeft: '',\n      paddingRight: ''\n    })\n  }\n\n  Modal.prototype.checkScrollbar = function () {\n    var fullWindowWidth = window.innerWidth\n    if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8\n      var documentElementRect = document.documentElement.getBoundingClientRect()\n      fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)\n    }\n    this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth\n    this.scrollbarWidth = this.measureScrollbar()\n  }\n\n  Modal.prototype.setScrollbar = function () {\n    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)\n    this.originalBodyPad = document.body.style.paddingRight || ''\n    var scrollbarWidth = this.scrollbarWidth\n    if (this.bodyIsOverflowing) {\n      this.$body.css('padding-right', bodyPad + scrollbarWidth)\n      $(this.fixedContent).each(function (index, element) {\n        var actualPadding = element.style.paddingRight\n        var calculatedPadding = $(element).css('padding-right')\n        $(element)\n          .data('padding-right', actualPadding)\n          .css('padding-right', parseFloat(calculatedPadding) + scrollbarWidth + 'px')\n      })\n    }\n  }\n\n  Modal.prototype.resetScrollbar = function () {\n    this.$body.css('padding-right', this.originalBodyPad)\n    $(this.fixedContent).each(function (index, element) {\n      var padding = $(element).data('padding-right')\n      $(element).removeData('padding-right')\n      element.style.paddingRight = padding ? padding : ''\n    })\n  }\n\n  Modal.prototype.measureScrollbar = function () { // thx walsh\n    var scrollDiv = document.createElement('div')\n    scrollDiv.className = 'modal-scrollbar-measure'\n    this.$body.append(scrollDiv)\n    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth\n    this.$body[0].removeChild(scrollDiv)\n    return scrollbarWidth\n  }\n\n\n  // MODAL PLUGIN DEFINITION\n  // =======================\n\n  function Plugin(option, _relatedTarget) {\n    return this.each(function () {\n      var $this = $(this)\n      var data = $this.data('bs.modal')\n      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))\n      if (typeof option == 'string') data[option](_relatedTarget)\n      else if (options.show) data.show(_relatedTarget)\n    })\n  }\n\n  var old = $.fn.modal\n\n  $.fn.modal = Plugin\n  $.fn.modal.Constructor = Modal\n\n\n  // MODAL NO CONFLICT\n  // =================\n\n  $.fn.modal.noConflict = function () {\n    $.fn.modal = old\n    return this\n  }\n\n\n  // MODAL DATA-API\n  // ==============\n\n  $(document).on('click.bs.modal.data-api', '[data-toggle=\"modal\"]', function (e) {\n    var $this = $(this)\n    var href = $this.attr('href')\n    var target = $this.attr('data-target') ||\n      (href && href.replace(/.*(?=#[^\\s]+$)/, '')) // strip for ie7\n\n    var $target = $(document).find(target)\n    var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())\n\n    if ($this.is('a')) e.preventDefault()\n\n    $target.one('show.bs.modal', function (showEvent) {\n      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown\n      $target.one('hidden.bs.modal', function () {\n        $this.is(':visible') && $this.trigger('focus')\n      })\n    })\n    Plugin.call($target, option, this)\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: tooltip.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#tooltip\n * Inspired by the original jQuery.tipsy by Jason Frame\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n+function ($) {\n  'use strict';\n\n  var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']\n\n  var uriAttrs = [\n    'background',\n    'cite',\n    'href',\n    'itemtype',\n    'longdesc',\n    'poster',\n    'src',\n    'xlink:href'\n  ]\n\n  var ARIA_ATTRIBUTE_PATTERN = /^aria-[\\w-]*$/i\n\n  var DefaultWhitelist = {\n    // Global attributes allowed on any supplied element below.\n    '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],\n    a: ['target', 'href', 'title', 'rel'],\n    area: [],\n    b: [],\n    br: [],\n    col: [],\n    code: [],\n    div: [],\n    em: [],\n    hr: [],\n    h1: [],\n    h2: [],\n    h3: [],\n    h4: [],\n    h5: [],\n    h6: [],\n    i: [],\n    img: ['src', 'alt', 'title', 'width', 'height'],\n    li: [],\n    ol: [],\n    p: [],\n    pre: [],\n    s: [],\n    small: [],\n    span: [],\n    sub: [],\n    sup: [],\n    strong: [],\n    u: [],\n    ul: []\n  }\n\n  /**\n   * A pattern that recognizes a commonly useful subset of URLs that are safe.\n   *\n   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n   */\n  var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi\n\n  /**\n   * A pattern that matches safe data URLs. Only matches image, video and audio types.\n   *\n   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts\n   */\n  var DATA_URL_PATTERN = /^data:(?:image\\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\\/(?:mpeg|mp4|ogg|webm)|audio\\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i\n\n  function allowedAttribute(attr, allowedAttributeList) {\n    var attrName = attr.nodeName.toLowerCase()\n\n    if ($.inArray(attrName, allowedAttributeList) !== -1) {\n      if ($.inArray(attrName, uriAttrs) !== -1) {\n        return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))\n      }\n\n      return true\n    }\n\n    var regExp = $(allowedAttributeList).filter(function (index, value) {\n      return value instanceof RegExp\n    })\n\n    // Check if a regular expression validates the attribute.\n    for (var i = 0, l = regExp.length; i < l; i++) {\n      if (attrName.match(regExp[i])) {\n        return true\n      }\n    }\n\n    return false\n  }\n\n  function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {\n    if (unsafeHtml.length === 0) {\n      return unsafeHtml\n    }\n\n    if (sanitizeFn && typeof sanitizeFn === 'function') {\n      return sanitizeFn(unsafeHtml)\n    }\n\n    // IE 8 and below don't support createHTMLDocument\n    if (!document.implementation || !document.implementation.createHTMLDocument) {\n      return unsafeHtml\n    }\n\n    var createdDocument = document.implementation.createHTMLDocument('sanitization')\n    createdDocument.body.innerHTML = unsafeHtml\n\n    var whitelistKeys = $.map(whiteList, function (el, i) { return i })\n    var elements = $(createdDocument.body).find('*')\n\n    for (var i = 0, len = elements.length; i < len; i++) {\n      var el = elements[i]\n      var elName = el.nodeName.toLowerCase()\n\n      if ($.inArray(elName, whitelistKeys) === -1) {\n        el.parentNode.removeChild(el)\n\n        continue\n      }\n\n      var attributeList = $.map(el.attributes, function (el) { return el })\n      var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])\n\n      for (var j = 0, len2 = attributeList.length; j < len2; j++) {\n        if (!allowedAttribute(attributeList[j], whitelistedAttributes)) {\n          el.removeAttribute(attributeList[j].nodeName)\n        }\n      }\n    }\n\n    return createdDocument.body.innerHTML\n  }\n\n  // TOOLTIP PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Tooltip = function (element, options) {\n    this.type       = null\n    this.options    = null\n    this.enabled    = null\n    this.timeout    = null\n    this.hoverState = null\n    this.$element   = null\n    this.inState    = null\n\n    this.init('tooltip', element, options)\n  }\n\n  Tooltip.VERSION  = '3.4.1'\n\n  Tooltip.TRANSITION_DURATION = 150\n\n  Tooltip.DEFAULTS = {\n    animation: true,\n    placement: 'top',\n    selector: false,\n    template: '<div class=\"tooltip\" role=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>',\n    trigger: 'hover focus',\n    title: '',\n    delay: 0,\n    html: false,\n    container: false,\n    viewport: {\n      selector: 'body',\n      padding: 0\n    },\n    sanitize : true,\n    sanitizeFn : null,\n    whiteList : DefaultWhitelist\n  }\n\n  Tooltip.prototype.init = function (type, element, options) {\n    this.enabled   = true\n    this.type      = type\n    this.$element  = $(element)\n    this.options   = this.getOptions(options)\n    this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))\n    this.inState   = { click: false, hover: false, focus: false }\n\n    if (this.$element[0] instanceof document.constructor && !this.options.selector) {\n      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')\n    }\n\n    var triggers = this.options.trigger.split(' ')\n\n    for (var i = triggers.length; i--;) {\n      var trigger = triggers[i]\n\n      if (trigger == 'click') {\n        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))\n      } else if (trigger != 'manual') {\n        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'\n        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'\n\n        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))\n        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))\n      }\n    }\n\n    this.options.selector ?\n      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :\n      this.fixTitle()\n  }\n\n  Tooltip.prototype.getDefaults = function () {\n    return Tooltip.DEFAULTS\n  }\n\n  Tooltip.prototype.getOptions = function (options) {\n    var dataAttributes = this.$element.data()\n\n    for (var dataAttr in dataAttributes) {\n      if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {\n        delete dataAttributes[dataAttr]\n      }\n    }\n\n    options = $.extend({}, this.getDefaults(), dataAttributes, options)\n\n    if (options.delay && typeof options.delay == 'number') {\n      options.delay = {\n        show: options.delay,\n        hide: options.delay\n      }\n    }\n\n    if (options.sanitize) {\n      options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn)\n    }\n\n    return options\n  }\n\n  Tooltip.prototype.getDelegateOptions = function () {\n    var options  = {}\n    var defaults = this.getDefaults()\n\n    this._options && $.each(this._options, function (key, value) {\n      if (defaults[key] != value) options[key] = value\n    })\n\n    return options\n  }\n\n  Tooltip.prototype.enter = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget).data('bs.' + this.type)\n\n    if (!self) {\n      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())\n      $(obj.currentTarget).data('bs.' + this.type, self)\n    }\n\n    if (obj instanceof $.Event) {\n      self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true\n    }\n\n    if (self.tip().hasClass('in') || self.hoverState == 'in') {\n      self.hoverState = 'in'\n      return\n    }\n\n    clearTimeout(self.timeout)\n\n    self.hoverState = 'in'\n\n    if (!self.options.delay || !self.options.delay.show) return self.show()\n\n    self.timeout = setTimeout(function () {\n      if (self.hoverState == 'in') self.show()\n    }, self.options.delay.show)\n  }\n\n  Tooltip.prototype.isInStateTrue = function () {\n    for (var key in this.inState) {\n      if (this.inState[key]) return true\n    }\n\n    return false\n  }\n\n  Tooltip.prototype.leave = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget).data('bs.' + this.type)\n\n    if (!self) {\n      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())\n      $(obj.currentTarget).data('bs.' + this.type, self)\n    }\n\n    if (obj instanceof $.Event) {\n      self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false\n    }\n\n    if (self.isInStateTrue()) return\n\n    clearTimeout(self.timeout)\n\n    self.hoverState = 'out'\n\n    if (!self.options.delay || !self.options.delay.hide) return self.hide()\n\n    self.timeout = setTimeout(function () {\n      if (self.hoverState == 'out') self.hide()\n    }, self.options.delay.hide)\n  }\n\n  Tooltip.prototype.show = function () {\n    var e = $.Event('show.bs.' + this.type)\n\n    if (this.hasContent() && this.enabled) {\n      this.$element.trigger(e)\n\n      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])\n      if (e.isDefaultPrevented() || !inDom) return\n      var that = this\n\n      var $tip = this.tip()\n\n      var tipId = this.getUID(this.type)\n\n      this.setContent()\n      $tip.attr('id', tipId)\n      this.$element.attr('aria-describedby', tipId)\n\n      if (this.options.animation) $tip.addClass('fade')\n\n      var placement = typeof this.options.placement == 'function' ?\n        this.options.placement.call(this, $tip[0], this.$element[0]) :\n        this.options.placement\n\n      var autoToken = /\\s?auto?\\s?/i\n      var autoPlace = autoToken.test(placement)\n      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'\n\n      $tip\n        .detach()\n        .css({ top: 0, left: 0, display: 'block' })\n        .addClass(placement)\n        .data('bs.' + this.type, this)\n\n      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)\n      this.$element.trigger('inserted.bs.' + this.type)\n\n      var pos          = this.getPosition()\n      var actualWidth  = $tip[0].offsetWidth\n      var actualHeight = $tip[0].offsetHeight\n\n      if (autoPlace) {\n        var orgPlacement = placement\n        var viewportDim = this.getPosition(this.$viewport)\n\n        placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top'    :\n                    placement == 'top'    && pos.top    - actualHeight < viewportDim.top    ? 'bottom' :\n                    placement == 'right'  && pos.right  + actualWidth  > viewportDim.width  ? 'left'   :\n                    placement == 'left'   && pos.left   - actualWidth  < viewportDim.left   ? 'right'  :\n                    placement\n\n        $tip\n          .removeClass(orgPlacement)\n          .addClass(placement)\n      }\n\n      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)\n\n      this.applyPlacement(calculatedOffset, placement)\n\n      var complete = function () {\n        var prevHoverState = that.hoverState\n        that.$element.trigger('shown.bs.' + that.type)\n        that.hoverState = null\n\n        if (prevHoverState == 'out') that.leave(that)\n      }\n\n      $.support.transition && this.$tip.hasClass('fade') ?\n        $tip\n          .one('bsTransitionEnd', complete)\n          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :\n        complete()\n    }\n  }\n\n  Tooltip.prototype.applyPlacement = function (offset, placement) {\n    var $tip   = this.tip()\n    var width  = $tip[0].offsetWidth\n    var height = $tip[0].offsetHeight\n\n    // manually read margins because getBoundingClientRect includes difference\n    var marginTop = parseInt($tip.css('margin-top'), 10)\n    var marginLeft = parseInt($tip.css('margin-left'), 10)\n\n    // we must check for NaN for ie 8/9\n    if (isNaN(marginTop))  marginTop  = 0\n    if (isNaN(marginLeft)) marginLeft = 0\n\n    offset.top  += marginTop\n    offset.left += marginLeft\n\n    // $.fn.offset doesn't round pixel values\n    // so we use setOffset directly with our own function B-0\n    $.offset.setOffset($tip[0], $.extend({\n      using: function (props) {\n        $tip.css({\n          top: Math.round(props.top),\n          left: Math.round(props.left)\n        })\n      }\n    }, offset), 0)\n\n    $tip.addClass('in')\n\n    // check to see if placing tip in new offset caused the tip to resize itself\n    var actualWidth  = $tip[0].offsetWidth\n    var actualHeight = $tip[0].offsetHeight\n\n    if (placement == 'top' && actualHeight != height) {\n      offset.top = offset.top + height - actualHeight\n    }\n\n    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)\n\n    if (delta.left) offset.left += delta.left\n    else offset.top += delta.top\n\n    var isVertical          = /top|bottom/.test(placement)\n    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight\n    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'\n\n    $tip.offset(offset)\n    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)\n  }\n\n  Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {\n    this.arrow()\n      .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n      .css(isVertical ? 'top' : 'left', '')\n  }\n\n  Tooltip.prototype.setContent = function () {\n    var $tip  = this.tip()\n    var title = this.getTitle()\n\n    if (this.options.html) {\n      if (this.options.sanitize) {\n        title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn)\n      }\n\n      $tip.find('.tooltip-inner').html(title)\n    } else {\n      $tip.find('.tooltip-inner').text(title)\n    }\n\n    $tip.removeClass('fade in top bottom left right')\n  }\n\n  Tooltip.prototype.hide = function (callback) {\n    var that = this\n    var $tip = $(this.$tip)\n    var e    = $.Event('hide.bs.' + this.type)\n\n    function complete() {\n      if (that.hoverState != 'in') $tip.detach()\n      if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.\n        that.$element\n          .removeAttr('aria-describedby')\n          .trigger('hidden.bs.' + that.type)\n      }\n      callback && callback()\n    }\n\n    this.$element.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    $tip.removeClass('in')\n\n    $.support.transition && $tip.hasClass('fade') ?\n      $tip\n        .one('bsTransitionEnd', complete)\n        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :\n      complete()\n\n    this.hoverState = null\n\n    return this\n  }\n\n  Tooltip.prototype.fixTitle = function () {\n    var $e = this.$element\n    if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {\n      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')\n    }\n  }\n\n  Tooltip.prototype.hasContent = function () {\n    return this.getTitle()\n  }\n\n  Tooltip.prototype.getPosition = function ($element) {\n    $element   = $element || this.$element\n\n    var el     = $element[0]\n    var isBody = el.tagName == 'BODY'\n\n    var elRect    = el.getBoundingClientRect()\n    if (elRect.width == null) {\n      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })\n    }\n    var isSvg = window.SVGElement && el instanceof window.SVGElement\n    // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.\n    // See https://github.com/twbs/bootstrap/issues/20280\n    var elOffset  = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())\n    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }\n    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null\n\n    return $.extend({}, elRect, scroll, outerDims, elOffset)\n  }\n\n  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {\n    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :\n           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :\n           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :\n        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }\n\n  }\n\n  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {\n    var delta = { top: 0, left: 0 }\n    if (!this.$viewport) return delta\n\n    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0\n    var viewportDimensions = this.getPosition(this.$viewport)\n\n    if (/right|left/.test(placement)) {\n      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll\n      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight\n      if (topEdgeOffset < viewportDimensions.top) { // top overflow\n        delta.top = viewportDimensions.top - topEdgeOffset\n      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset\n      }\n    } else {\n      var leftEdgeOffset  = pos.left - viewportPadding\n      var rightEdgeOffset = pos.left + viewportPadding + actualWidth\n      if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n        delta.left = viewportDimensions.left - leftEdgeOffset\n      } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow\n        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset\n      }\n    }\n\n    return delta\n  }\n\n  Tooltip.prototype.getTitle = function () {\n    var title\n    var $e = this.$element\n    var o  = this.options\n\n    title = $e.attr('data-original-title')\n      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)\n\n    return title\n  }\n\n  Tooltip.prototype.getUID = function (prefix) {\n    do prefix += ~~(Math.random() * 1000000)\n    while (document.getElementById(prefix))\n    return prefix\n  }\n\n  Tooltip.prototype.tip = function () {\n    if (!this.$tip) {\n      this.$tip = $(this.options.template)\n      if (this.$tip.length != 1) {\n        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')\n      }\n    }\n    return this.$tip\n  }\n\n  Tooltip.prototype.arrow = function () {\n    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))\n  }\n\n  Tooltip.prototype.enable = function () {\n    this.enabled = true\n  }\n\n  Tooltip.prototype.disable = function () {\n    this.enabled = false\n  }\n\n  Tooltip.prototype.toggleEnabled = function () {\n    this.enabled = !this.enabled\n  }\n\n  Tooltip.prototype.toggle = function (e) {\n    var self = this\n    if (e) {\n      self = $(e.currentTarget).data('bs.' + this.type)\n      if (!self) {\n        self = new this.constructor(e.currentTarget, this.getDelegateOptions())\n        $(e.currentTarget).data('bs.' + this.type, self)\n      }\n    }\n\n    if (e) {\n      self.inState.click = !self.inState.click\n      if (self.isInStateTrue()) self.enter(self)\n      else self.leave(self)\n    } else {\n      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)\n    }\n  }\n\n  Tooltip.prototype.destroy = function () {\n    var that = this\n    clearTimeout(this.timeout)\n    this.hide(function () {\n      that.$element.off('.' + that.type).removeData('bs.' + that.type)\n      if (that.$tip) {\n        that.$tip.detach()\n      }\n      that.$tip = null\n      that.$arrow = null\n      that.$viewport = null\n      that.$element = null\n    })\n  }\n\n  Tooltip.prototype.sanitizeHtml = function (unsafeHtml) {\n    return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn)\n  }\n\n  // TOOLTIP PLUGIN DEFINITION\n  // =========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.tooltip')\n      var options = typeof option == 'object' && option\n\n      if (!data && /destroy|hide/.test(option)) return\n      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.tooltip\n\n  $.fn.tooltip             = Plugin\n  $.fn.tooltip.Constructor = Tooltip\n\n\n  // TOOLTIP NO CONFLICT\n  // ===================\n\n  $.fn.tooltip.noConflict = function () {\n    $.fn.tooltip = old\n    return this\n  }\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: popover.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#popovers\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // POPOVER PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Popover = function (element, options) {\n    this.init('popover', element, options)\n  }\n\n  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')\n\n  Popover.VERSION  = '3.4.1'\n\n  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {\n    placement: 'right',\n    trigger: 'click',\n    content: '',\n    template: '<div class=\"popover\" role=\"tooltip\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'\n  })\n\n\n  // NOTE: POPOVER EXTENDS tooltip.js\n  // ================================\n\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)\n\n  Popover.prototype.constructor = Popover\n\n  Popover.prototype.getDefaults = function () {\n    return Popover.DEFAULTS\n  }\n\n  Popover.prototype.setContent = function () {\n    var $tip    = this.tip()\n    var title   = this.getTitle()\n    var content = this.getContent()\n\n    if (this.options.html) {\n      var typeContent = typeof content\n\n      if (this.options.sanitize) {\n        title = this.sanitizeHtml(title)\n\n        if (typeContent === 'string') {\n          content = this.sanitizeHtml(content)\n        }\n      }\n\n      $tip.find('.popover-title').html(title)\n      $tip.find('.popover-content').children().detach().end()[\n        typeContent === 'string' ? 'html' : 'append'\n      ](content)\n    } else {\n      $tip.find('.popover-title').text(title)\n      $tip.find('.popover-content').children().detach().end().text(content)\n    }\n\n    $tip.removeClass('fade top bottom left right in')\n\n    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do\n    // this manually by checking the contents.\n    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()\n  }\n\n  Popover.prototype.hasContent = function () {\n    return this.getTitle() || this.getContent()\n  }\n\n  Popover.prototype.getContent = function () {\n    var $e = this.$element\n    var o  = this.options\n\n    return $e.attr('data-content')\n      || (typeof o.content == 'function' ?\n        o.content.call($e[0]) :\n        o.content)\n  }\n\n  Popover.prototype.arrow = function () {\n    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))\n  }\n\n\n  // POPOVER PLUGIN DEFINITION\n  // =========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.popover')\n      var options = typeof option == 'object' && option\n\n      if (!data && /destroy|hide/.test(option)) return\n      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.popover\n\n  $.fn.popover             = Plugin\n  $.fn.popover.Constructor = Popover\n\n\n  // POPOVER NO CONFLICT\n  // ===================\n\n  $.fn.popover.noConflict = function () {\n    $.fn.popover = old\n    return this\n  }\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: scrollspy.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#scrollspy\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // SCROLLSPY CLASS DEFINITION\n  // ==========================\n\n  function ScrollSpy(element, options) {\n    this.$body          = $(document.body)\n    this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)\n    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)\n    this.selector       = (this.options.target || '') + ' .nav li > a'\n    this.offsets        = []\n    this.targets        = []\n    this.activeTarget   = null\n    this.scrollHeight   = 0\n\n    this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))\n    this.refresh()\n    this.process()\n  }\n\n  ScrollSpy.VERSION  = '3.4.1'\n\n  ScrollSpy.DEFAULTS = {\n    offset: 10\n  }\n\n  ScrollSpy.prototype.getScrollHeight = function () {\n    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)\n  }\n\n  ScrollSpy.prototype.refresh = function () {\n    var that          = this\n    var offsetMethod  = 'offset'\n    var offsetBase    = 0\n\n    this.offsets      = []\n    this.targets      = []\n    this.scrollHeight = this.getScrollHeight()\n\n    if (!$.isWindow(this.$scrollElement[0])) {\n      offsetMethod = 'position'\n      offsetBase   = this.$scrollElement.scrollTop()\n    }\n\n    this.$body\n      .find(this.selector)\n      .map(function () {\n        var $el   = $(this)\n        var href  = $el.data('target') || $el.attr('href')\n        var $href = /^#./.test(href) && $(href)\n\n        return ($href\n          && $href.length\n          && $href.is(':visible')\n          && [[$href[offsetMethod]().top + offsetBase, href]]) || null\n      })\n      .sort(function (a, b) { return a[0] - b[0] })\n      .each(function () {\n        that.offsets.push(this[0])\n        that.targets.push(this[1])\n      })\n  }\n\n  ScrollSpy.prototype.process = function () {\n    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset\n    var scrollHeight = this.getScrollHeight()\n    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()\n    var offsets      = this.offsets\n    var targets      = this.targets\n    var activeTarget = this.activeTarget\n    var i\n\n    if (this.scrollHeight != scrollHeight) {\n      this.refresh()\n    }\n\n    if (scrollTop >= maxScroll) {\n      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)\n    }\n\n    if (activeTarget && scrollTop < offsets[0]) {\n      this.activeTarget = null\n      return this.clear()\n    }\n\n    for (i = offsets.length; i--;) {\n      activeTarget != targets[i]\n        && scrollTop >= offsets[i]\n        && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])\n        && this.activate(targets[i])\n    }\n  }\n\n  ScrollSpy.prototype.activate = function (target) {\n    this.activeTarget = target\n\n    this.clear()\n\n    var selector = this.selector +\n      '[data-target=\"' + target + '\"],' +\n      this.selector + '[href=\"' + target + '\"]'\n\n    var active = $(selector)\n      .parents('li')\n      .addClass('active')\n\n    if (active.parent('.dropdown-menu').length) {\n      active = active\n        .closest('li.dropdown')\n        .addClass('active')\n    }\n\n    active.trigger('activate.bs.scrollspy')\n  }\n\n  ScrollSpy.prototype.clear = function () {\n    $(this.selector)\n      .parentsUntil(this.options.target, '.active')\n      .removeClass('active')\n  }\n\n\n  // SCROLLSPY PLUGIN DEFINITION\n  // ===========================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.scrollspy')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.scrollspy\n\n  $.fn.scrollspy             = Plugin\n  $.fn.scrollspy.Constructor = ScrollSpy\n\n\n  // SCROLLSPY NO CONFLICT\n  // =====================\n\n  $.fn.scrollspy.noConflict = function () {\n    $.fn.scrollspy = old\n    return this\n  }\n\n\n  // SCROLLSPY DATA-API\n  // ==================\n\n  $(window).on('load.bs.scrollspy.data-api', function () {\n    $('[data-spy=\"scroll\"]').each(function () {\n      var $spy = $(this)\n      Plugin.call($spy, $spy.data())\n    })\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: tab.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#tabs\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // TAB CLASS DEFINITION\n  // ====================\n\n  var Tab = function (element) {\n    // jscs:disable requireDollarBeforejQueryAssignment\n    this.element = $(element)\n    // jscs:enable requireDollarBeforejQueryAssignment\n  }\n\n  Tab.VERSION = '3.4.1'\n\n  Tab.TRANSITION_DURATION = 150\n\n  Tab.prototype.show = function () {\n    var $this    = this.element\n    var $ul      = $this.closest('ul:not(.dropdown-menu)')\n    var selector = $this.data('target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    if ($this.parent('li').hasClass('active')) return\n\n    var $previous = $ul.find('.active:last a')\n    var hideEvent = $.Event('hide.bs.tab', {\n      relatedTarget: $this[0]\n    })\n    var showEvent = $.Event('show.bs.tab', {\n      relatedTarget: $previous[0]\n    })\n\n    $previous.trigger(hideEvent)\n    $this.trigger(showEvent)\n\n    if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return\n\n    var $target = $(document).find(selector)\n\n    this.activate($this.closest('li'), $ul)\n    this.activate($target, $target.parent(), function () {\n      $previous.trigger({\n        type: 'hidden.bs.tab',\n        relatedTarget: $this[0]\n      })\n      $this.trigger({\n        type: 'shown.bs.tab',\n        relatedTarget: $previous[0]\n      })\n    })\n  }\n\n  Tab.prototype.activate = function (element, container, callback) {\n    var $active    = container.find('> .active')\n    var transition = callback\n      && $.support.transition\n      && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)\n\n    function next() {\n      $active\n        .removeClass('active')\n        .find('> .dropdown-menu > .active')\n        .removeClass('active')\n        .end()\n        .find('[data-toggle=\"tab\"]')\n        .attr('aria-expanded', false)\n\n      element\n        .addClass('active')\n        .find('[data-toggle=\"tab\"]')\n        .attr('aria-expanded', true)\n\n      if (transition) {\n        element[0].offsetWidth // reflow for transition\n        element.addClass('in')\n      } else {\n        element.removeClass('fade')\n      }\n\n      if (element.parent('.dropdown-menu').length) {\n        element\n          .closest('li.dropdown')\n          .addClass('active')\n          .end()\n          .find('[data-toggle=\"tab\"]')\n          .attr('aria-expanded', true)\n      }\n\n      callback && callback()\n    }\n\n    $active.length && transition ?\n      $active\n        .one('bsTransitionEnd', next)\n        .emulateTransitionEnd(Tab.TRANSITION_DURATION) :\n      next()\n\n    $active.removeClass('in')\n  }\n\n\n  // TAB PLUGIN DEFINITION\n  // =====================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.tab')\n\n      if (!data) $this.data('bs.tab', (data = new Tab(this)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.tab\n\n  $.fn.tab             = Plugin\n  $.fn.tab.Constructor = Tab\n\n\n  // TAB NO CONFLICT\n  // ===============\n\n  $.fn.tab.noConflict = function () {\n    $.fn.tab = old\n    return this\n  }\n\n\n  // TAB DATA-API\n  // ============\n\n  var clickHandler = function (e) {\n    e.preventDefault()\n    Plugin.call($(this), 'show')\n  }\n\n  $(document)\n    .on('click.bs.tab.data-api', '[data-toggle=\"tab\"]', clickHandler)\n    .on('click.bs.tab.data-api', '[data-toggle=\"pill\"]', clickHandler)\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: affix.js v3.4.1\n * https://getbootstrap.com/docs/3.4/javascript/#affix\n * ========================================================================\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n\n\n+function ($) {\n  'use strict';\n\n  // AFFIX CLASS DEFINITION\n  // ======================\n\n  var Affix = function (element, options) {\n    this.options = $.extend({}, Affix.DEFAULTS, options)\n\n    var target = this.options.target === Affix.DEFAULTS.target ? $(this.options.target) : $(document).find(this.options.target)\n\n    this.$target = target\n      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))\n      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))\n\n    this.$element     = $(element)\n    this.affixed      = null\n    this.unpin        = null\n    this.pinnedOffset = null\n\n    this.checkPosition()\n  }\n\n  Affix.VERSION  = '3.4.1'\n\n  Affix.RESET    = 'affix affix-top affix-bottom'\n\n  Affix.DEFAULTS = {\n    offset: 0,\n    target: window\n  }\n\n  Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {\n    var scrollTop    = this.$target.scrollTop()\n    var position     = this.$element.offset()\n    var targetHeight = this.$target.height()\n\n    if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false\n\n    if (this.affixed == 'bottom') {\n      if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'\n      return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'\n    }\n\n    var initializing   = this.affixed == null\n    var colliderTop    = initializing ? scrollTop : position.top\n    var colliderHeight = initializing ? targetHeight : height\n\n    if (offsetTop != null && scrollTop <= offsetTop) return 'top'\n    if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'\n\n    return false\n  }\n\n  Affix.prototype.getPinnedOffset = function () {\n    if (this.pinnedOffset) return this.pinnedOffset\n    this.$element.removeClass(Affix.RESET).addClass('affix')\n    var scrollTop = this.$target.scrollTop()\n    var position  = this.$element.offset()\n    return (this.pinnedOffset = position.top - scrollTop)\n  }\n\n  Affix.prototype.checkPositionWithEventLoop = function () {\n    setTimeout($.proxy(this.checkPosition, this), 1)\n  }\n\n  Affix.prototype.checkPosition = function () {\n    if (!this.$element.is(':visible')) return\n\n    var height       = this.$element.height()\n    var offset       = this.options.offset\n    var offsetTop    = offset.top\n    var offsetBottom = offset.bottom\n    var scrollHeight = Math.max($(document).height(), $(document.body).height())\n\n    if (typeof offset != 'object')         offsetBottom = offsetTop = offset\n    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)\n    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)\n\n    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)\n\n    if (this.affixed != affix) {\n      if (this.unpin != null) this.$element.css('top', '')\n\n      var affixType = 'affix' + (affix ? '-' + affix : '')\n      var e         = $.Event(affixType + '.bs.affix')\n\n      this.$element.trigger(e)\n\n      if (e.isDefaultPrevented()) return\n\n      this.affixed = affix\n      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null\n\n      this.$element\n        .removeClass(Affix.RESET)\n        .addClass(affixType)\n        .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')\n    }\n\n    if (affix == 'bottom') {\n      this.$element.offset({\n        top: scrollHeight - height - offsetBottom\n      })\n    }\n  }\n\n\n  // AFFIX PLUGIN DEFINITION\n  // =======================\n\n  function Plugin(option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.affix')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  var old = $.fn.affix\n\n  $.fn.affix             = Plugin\n  $.fn.affix.Constructor = Affix\n\n\n  // AFFIX NO CONFLICT\n  // =================\n\n  $.fn.affix.noConflict = function () {\n    $.fn.affix = old\n    return this\n  }\n\n\n  // AFFIX DATA-API\n  // ==============\n\n  $(window).on('load', function () {\n    $('[data-spy=\"affix\"]').each(function () {\n      var $spy = $(this)\n      var data = $spy.data()\n\n      data.offset = data.offset || {}\n\n      if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom\n      if (data.offsetTop    != null) data.offset.top    = data.offsetTop\n\n      Plugin.call($spy, data)\n    })\n  })\n\n}(jQuery);\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Scripts/jquery-3.4.1.js",
    "content": "/*!\n * jQuery JavaScript Library v3.4.1\n * https://jquery.com/\n *\n * Includes Sizzle.js\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://jquery.org/license\n *\n * Date: 2019-05-01T21:04Z\n */\n( function( global, factory ) {\n\n\t\"use strict\";\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n} )( typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1\n// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode\n// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common\n// enough that all such attempts are guarded in a try block.\n\"use strict\";\n\nvar arr = [];\n\nvar document = window.document;\n\nvar getProto = Object.getPrototypeOf;\n\nvar slice = arr.slice;\n\nvar concat = arr.concat;\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar fnToString = hasOwn.toString;\n\nvar ObjectFunctionString = fnToString.call( Object );\n\nvar support = {};\n\nvar isFunction = function isFunction( obj ) {\n\n      // Support: Chrome <=57, Firefox <=52\n      // In some browsers, typeof returns \"function\" for HTML <object> elements\n      // (i.e., `typeof document.createElement( \"object\" ) === \"function\"`).\n      // We don't want to classify *any* DOM node as a function.\n      return typeof obj === \"function\" && typeof obj.nodeType !== \"number\";\n  };\n\n\nvar isWindow = function isWindow( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t};\n\n\n\n\n\tvar preservedScriptAttributes = {\n\t\ttype: true,\n\t\tsrc: true,\n\t\tnonce: true,\n\t\tnoModule: true\n\t};\n\n\tfunction DOMEval( code, node, doc ) {\n\t\tdoc = doc || document;\n\n\t\tvar i, val,\n\t\t\tscript = doc.createElement( \"script\" );\n\n\t\tscript.text = code;\n\t\tif ( node ) {\n\t\t\tfor ( i in preservedScriptAttributes ) {\n\n\t\t\t\t// Support: Firefox 64+, Edge 18+\n\t\t\t\t// Some browsers don't support the \"nonce\" property on scripts.\n\t\t\t\t// On the other hand, just using `getAttribute` is not enough as\n\t\t\t\t// the `nonce` attribute is reset to an empty string whenever it\n\t\t\t\t// becomes browsing-context connected.\n\t\t\t\t// See https://github.com/whatwg/html/issues/2369\n\t\t\t\t// See https://html.spec.whatwg.org/#nonce-attributes\n\t\t\t\t// The `node.getAttribute` check was added for the sake of\n\t\t\t\t// `jQuery.globalEval` so that it can fake a nonce-containing node\n\t\t\t\t// via an object.\n\t\t\t\tval = node[ i ] || node.getAttribute && node.getAttribute( i );\n\t\t\t\tif ( val ) {\n\t\t\t\t\tscript.setAttribute( i, val );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdoc.head.appendChild( script ).parentNode.removeChild( script );\n\t}\n\n\nfunction toType( obj ) {\n\tif ( obj == null ) {\n\t\treturn obj + \"\";\n\t}\n\n\t// Support: Android <=2.3 only (functionish RegExp)\n\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\tclass2type[ toString.call( obj ) ] || \"object\" :\n\t\ttypeof obj;\n}\n/* global Symbol */\n// Defining this global in .eslintrc.json would create a danger of using the global\n// unguarded in another place, it seems safer to define global only for this module\n\n\n\nvar\n\tversion = \"3.4.1\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Support: Android <=4.0 only\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;\n\njQuery.fn = jQuery.prototype = {\n\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\n\t\t// Return all the elements in a clean array\n\t\tif ( num == null ) {\n\t\t\treturn slice.call( this );\n\t\t}\n\n\t\t// Return just the one element from the set\n\t\treturn num < 0 ? this[ num + this.length ] : this[ num ];\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\teach: function( callback ) {\n\t\treturn jQuery.each( this, callback );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map( this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t} ) );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor();\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[ 0 ] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// Skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !isFunction( target ) ) {\n\t\ttarget = {};\n\t}\n\n\t// Extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\n\t\t// Only deal with non-null/undefined values\n\t\tif ( ( options = arguments[ i ] ) != null ) {\n\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent Object.prototype pollution\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( name === \"__proto__\" || target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject( copy ) ||\n\t\t\t\t\t( copyIsArray = Array.isArray( copy ) ) ) ) {\n\t\t\t\t\tsrc = target[ name ];\n\n\t\t\t\t\t// Ensure proper type for the source value\n\t\t\t\t\tif ( copyIsArray && !Array.isArray( src ) ) {\n\t\t\t\t\t\tclone = [];\n\t\t\t\t\t} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {\n\t\t\t\t\t\tclone = {};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src;\n\t\t\t\t\t}\n\t\t\t\t\tcopyIsArray = false;\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend( {\n\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\tisPlainObject: function( obj ) {\n\t\tvar proto, Ctor;\n\n\t\t// Detect obvious negatives\n\t\t// Use toString instead of jQuery.type to catch host objects\n\t\tif ( !obj || toString.call( obj ) !== \"[object Object]\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tproto = getProto( obj );\n\n\t\t// Objects with no prototype (e.g., `Object.create( null )`) are plain\n\t\tif ( !proto ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Objects with prototype are plain iff they were constructed by a global Object function\n\t\tCtor = hasOwn.call( proto, \"constructor\" ) && proto.constructor;\n\t\treturn typeof Ctor === \"function\" && fnToString.call( Ctor ) === ObjectFunctionString;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( code, options ) {\n\t\tDOMEval( code, { nonce: options && options.nonce } );\n\t},\n\n\teach: function( obj, callback ) {\n\t\tvar length, i = 0;\n\n\t\tif ( isArrayLike( obj ) ) {\n\t\t\tlength = obj.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( i in obj ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Support: Android <=4.0 only\n\ttrim: function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArrayLike( Object( arr ) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t},\n\n\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t// push.apply(_, arraylike) throws on ancient WebKit\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar length, value,\n\t\t\ti = 0,\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArrayLike( elems ) ) {\n\t\t\tlength = elems.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n} );\n\nif ( typeof Symbol === \"function\" ) {\n\tjQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];\n}\n\n// Populate the class2type map\njQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".split( \" \" ),\nfunction( i, name ) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n} );\n\nfunction isArrayLike( obj ) {\n\n\t// Support: real iOS 8.2 only (not reproducible in simulator)\n\t// `in` check used to prevent JIT error (gh-2145)\n\t// hasOwn isn't used here due to false negatives\n\t// regarding Nodelist length in IE\n\tvar length = !!obj && \"length\" in obj && obj.length,\n\t\ttype = toType( obj );\n\n\tif ( isFunction( obj ) || isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.3.4\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://js.foundation/\n *\n * Date: 2019-04-08\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tnonnativeSelectorCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// https://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\n\t// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = \"(?:\\\\\\\\.|[\\\\w-]|[^\\0-\\\\xa0])+\",\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace +\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\"*\\\\]\",\n\n\tpseudos = \":(\" + identifier + \")(?:\\\\((\" +\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\trdescend = new RegExp( whitespace + \"|>\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + identifier + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + identifier + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + identifier + \"|[*])\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trhtml = /HTML$/i,\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\n\t// CSS escapes\n\t// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// CSS string/identifier serialization\n\t// https://drafts.csswg.org/cssom/#common-serializing-idioms\n\trcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,\n\tfcssescape = function( ch, asCodePoint ) {\n\t\tif ( asCodePoint ) {\n\n\t\t\t// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\n\t\t\tif ( ch === \"\\0\" ) {\n\t\t\t\treturn \"\\uFFFD\";\n\t\t\t}\n\n\t\t\t// Control characters and (dependent upon position) numbers get escaped as code points\n\t\t\treturn ch.slice( 0, -1 ) + \"\\\\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + \" \";\n\t\t}\n\n\t\t// Other potentially-special ASCII characters get backslash-escaped\n\t\treturn \"\\\\\" + ch;\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t},\n\n\tinDisabledFieldset = addCombinator(\n\t\tfunction( elem ) {\n\t\t\treturn elem.disabled === true && elem.nodeName.toLowerCase() === \"fieldset\";\n\t\t},\n\t\t{ dir: \"parentNode\", next: \"legend\" }\n\t);\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar m, i, elem, nid, match, groups, newSelector,\n\t\tnewContext = context && context.ownerDocument,\n\n\t\t// nodeType defaults to 9, since context defaults to document\n\t\tnodeType = context ? context.nodeType : 9;\n\n\tresults = results || [];\n\n\t// Return early from calls with invalid selector or context\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\t// Try to shortcut find operations (as opposed to filters) in HTML documents\n\tif ( !seed ) {\n\n\t\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\t\tsetDocument( context );\n\t\t}\n\t\tcontext = context || document;\n\n\t\tif ( documentIsHTML ) {\n\n\t\t\t// If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n\t\t\t// (excepting DocumentFragment context, where the methods don't exist)\n\t\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\n\t\t\t\t// ID selector\n\t\t\t\tif ( (m = match[1]) ) {\n\n\t\t\t\t\t// Document context\n\t\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\t\tif ( (elem = context.getElementById( m )) ) {\n\n\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// Element context\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\tif ( newContext && (elem = newContext.getElementById( m )) &&\n\t\t\t\t\t\t\tcontains( context, elem ) &&\n\t\t\t\t\t\t\telem.id === m ) {\n\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t// Type selector\n\t\t\t\t} else if ( match[2] ) {\n\t\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\t\treturn results;\n\n\t\t\t\t// Class selector\n\t\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName &&\n\t\t\t\t\tcontext.getElementsByClassName ) {\n\n\t\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Take advantage of querySelectorAll\n\t\t\tif ( support.qsa &&\n\t\t\t\t!nonnativeSelectorCache[ selector + \" \" ] &&\n\t\t\t\t(!rbuggyQSA || !rbuggyQSA.test( selector )) &&\n\n\t\t\t\t// Support: IE 8 only\n\t\t\t\t// Exclude object elements\n\t\t\t\t(nodeType !== 1 || context.nodeName.toLowerCase() !== \"object\") ) {\n\n\t\t\t\tnewSelector = selector;\n\t\t\t\tnewContext = context;\n\n\t\t\t\t// qSA considers elements outside a scoping root when evaluating child or\n\t\t\t\t// descendant combinators, which is not what we want.\n\t\t\t\t// In such cases, we work around the behavior by prefixing every selector in the\n\t\t\t\t// list with an ID selector referencing the scope context.\n\t\t\t\t// Thanks to Andrew Dupont for this technique.\n\t\t\t\tif ( nodeType === 1 && rdescend.test( selector ) ) {\n\n\t\t\t\t\t// Capture the context ID, setting it first if necessary\n\t\t\t\t\tif ( (nid = context.getAttribute( \"id\" )) ) {\n\t\t\t\t\t\tnid = nid.replace( rcssescape, fcssescape );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", (nid = expando) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prefix every selector in the list\n\t\t\t\t\tgroups = tokenize( selector );\n\t\t\t\t\ti = groups.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tgroups[i] = \"#\" + nid + \" \" + toSelector( groups[i] );\n\t\t\t\t\t}\n\t\t\t\t\tnewSelector = groups.join( \",\" );\n\n\t\t\t\t\t// Expand context for sibling selectors\n\t\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\tcontext;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch ( qsaError ) {\n\t\t\t\t\tnonnativeSelectorCache( selector, true );\n\t\t\t\t} finally {\n\t\t\t\t\tif ( nid === expando ) {\n\t\t\t\t\t\tcontext.removeAttribute( \"id\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {function(string, object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created element and returns a boolean result\n */\nfunction assert( fn ) {\n\tvar el = document.createElement(\"fieldset\");\n\n\ttry {\n\t\treturn !!fn( el );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( el.parentNode ) {\n\t\t\tel.parentNode.removeChild( el );\n\t\t}\n\t\t// release memory in IE\n\t\tel = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = arr.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\ta.sourceIndex - b.sourceIndex;\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for :enabled/:disabled\n * @param {Boolean} disabled true for :disabled; false for :enabled\n */\nfunction createDisabledPseudo( disabled ) {\n\n\t// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable\n\treturn function( elem ) {\n\n\t\t// Only certain elements can match :enabled or :disabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled\n\t\tif ( \"form\" in elem ) {\n\n\t\t\t// Check for inherited disabledness on relevant non-disabled elements:\n\t\t\t// * listed form-associated elements in a disabled fieldset\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#category-listed\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled\n\t\t\t// * option elements in a disabled optgroup\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled\n\t\t\t// All such elements have a \"form\" property.\n\t\t\tif ( elem.parentNode && elem.disabled === false ) {\n\n\t\t\t\t// Option elements defer to a parent optgroup if present\n\t\t\t\tif ( \"label\" in elem ) {\n\t\t\t\t\tif ( \"label\" in elem.parentNode ) {\n\t\t\t\t\t\treturn elem.parentNode.disabled === disabled;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.disabled === disabled;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Support: IE 6 - 11\n\t\t\t\t// Use the isDisabled shortcut property to check for disabled fieldset ancestors\n\t\t\t\treturn elem.isDisabled === disabled ||\n\n\t\t\t\t\t// Where there is no isDisabled, check manually\n\t\t\t\t\t/* jshint -W018 */\n\t\t\t\t\telem.isDisabled !== !disabled &&\n\t\t\t\t\t\tinDisabledFieldset( elem ) === disabled;\n\t\t\t}\n\n\t\t\treturn elem.disabled === disabled;\n\n\t\t// Try to winnow out elements that can't be disabled before trusting the disabled property.\n\t\t// Some victims get caught in our net (label, legend, menu, track), but it shouldn't\n\t\t// even exist on them, let alone have a boolean value.\n\t\t} else if ( \"label\" in elem ) {\n\t\t\treturn elem.disabled === disabled;\n\t\t}\n\n\t\t// Remaining elements are neither :enabled nor :disabled\n\t\treturn false;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\tvar namespace = elem.namespaceURI,\n\t\tdocElem = (elem.ownerDocument || elem).documentElement;\n\n\t// Support: IE <=8\n\t// Assume HTML when documentElement doesn't yet exist, such as inside loading iframes\n\t// https://bugs.jquery.com/ticket/4833\n\treturn !rhtml.test( namespace || docElem && docElem.nodeName || \"HTML\" );\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, subWindow,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// Return early if doc is invalid or already selected\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Update global variables\n\tdocument = doc;\n\tdocElem = document.documentElement;\n\tdocumentIsHTML = !isXML( document );\n\n\t// Support: IE 9-11, Edge\n\t// Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n\tif ( preferredDoc !== document &&\n\t\t(subWindow = document.defaultView) && subWindow.top !== subWindow ) {\n\n\t\t// Support: IE 11, Edge\n\t\tif ( subWindow.addEventListener ) {\n\t\t\tsubWindow.addEventListener( \"unload\", unloadHandler, false );\n\n\t\t// Support: IE 9 - 10 only\n\t\t} else if ( subWindow.attachEvent ) {\n\t\t\tsubWindow.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert(function( el ) {\n\t\tel.className = \"i\";\n\t\treturn !el.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( el ) {\n\t\tel.appendChild( document.createComment(\"\") );\n\t\treturn !el.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( document.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programmatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( el ) {\n\t\tdocElem.appendChild( el ).id = expando;\n\t\treturn !document.getElementsByName || !document.getElementsByName( expando ).length;\n\t});\n\n\t// ID filter and find\n\tif ( support.getById ) {\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar elem = context.getElementById( id );\n\t\t\t\treturn elem ? [ elem ] : [];\n\t\t\t}\n\t\t};\n\t} else {\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" &&\n\t\t\t\t\telem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\n\t\t// Support: IE 6 - 7 only\n\t\t// getElementById is not reliable as a find shortcut\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar node, i, elems,\n\t\t\t\t\telem = context.getElementById( id );\n\n\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t// Verify the id attribute\n\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fall back on getElementsByName\n\t\t\t\t\telems = context.getElementsByName( id );\n\t\t\t\t\ti = 0;\n\t\t\t\t\twhile ( (elem = elems[i++]) ) {\n\t\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn [];\n\t\t\t}\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See https://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( document.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( el ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// https://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( el ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\r\\\\' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( el.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !el.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\t\t\tif ( !el.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !el.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibling-combinator selector` fails\n\t\t\tif ( !el.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( el ) {\n\t\t\tel.innerHTML = \"<a href='' disabled='disabled'></a>\" +\n\t\t\t\t\"<select disabled='disabled'><option/></select>\";\n\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = document.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tel.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( el.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( el.querySelectorAll(\":enabled\").length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// IE's :disabled selector does not pick up the children of disabled fieldsets\n\t\t\tdocElem.appendChild( el ).disabled = true;\n\t\t\tif ( el.querySelectorAll(\":disabled\").length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tel.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( el ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( el, \"*\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( el, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully self-exclusive\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === document ? -1 :\n\t\t\t\tb === document ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn document;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t!nonnativeSelectorCache[ expr + \" \" ] &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tnonnativeSelectorCache( expr, true );\n\t\t}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.escape = function( sel ) {\n\treturn (sel + \"\").replace( rcssescape, fcssescape );\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, uniqueCache, outerCache, node, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType,\n\t\t\t\t\t\tdiff = false;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) {\n\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\n\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\tnode = parent;\n\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\tdiff = nodeIndex && cache[ 2 ];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\tdiff = nodeIndex;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// xml :nth-child(...)\n\t\t\t\t\t\t\t// or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t\tif ( diff === false ) {\n\t\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t\tif ( ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) &&\n\t\t\t\t\t\t\t\t\t\t++diff ) {\n\n\t\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[0] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": createDisabledPseudo( false ),\n\t\t\"disabled\": createDisabledPseudo( true ),\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ?\n\t\t\t\targument + length :\n\t\t\t\targument > length ?\n\t\t\t\t\tlength :\n\t\t\t\t\targument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tskip = combinator.next,\n\t\tkey = skip || dir,\n\t\tcheckNonElements = base && key === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, uniqueCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\n\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\tuniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});\n\n\t\t\t\t\t\tif ( skip && skip === elem.nodeName.toLowerCase() ) {\n\t\t\t\t\t\t\telem = elem[ dir ] || elem;\n\t\t\t\t\t\t} else if ( (oldCache = uniqueCache[ key ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\tuniqueCache[ key ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context === document || context || outermost;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\tif ( !context && elem.ownerDocument !== document ) {\n\t\t\t\t\t\tsetDocument( elem );\n\t\t\t\t\t\txml = !documentIsHTML;\n\t\t\t\t\t}\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context || document, xml) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// `i` is now the count of elements visited above, and adding it to `matchedCount`\n\t\t\t// makes the latter nonnegative.\n\t\t\tmatchedCount += i;\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\t// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n\t\t\t// equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n\t\t\t// no element matchers and no seed.\n\t\t\t// Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n\t\t\t// case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n\t\t\t// numerically zero.\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is only one selector in the list and no seed\n\t// (the latter of which guarantees us context)\n\tif ( match.length === 1 ) {\n\n\t\t// Reduce context if the leading compound selector is an ID\n\t\ttokens = match[0] = match[0].slice( 0 );\n\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\tcontext.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\t!context || rsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( el ) {\n\t// Should return 1, but returns 4 (following)\n\treturn el.compareDocumentPosition( document.createElement(\"fieldset\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( el ) {\n\tel.innerHTML = \"<a href='#'></a>\";\n\treturn el.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( el ) {\n\tel.innerHTML = \"<input/>\";\n\tel.firstChild.setAttribute( \"value\", \"\" );\n\treturn el.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( el ) {\n\treturn el.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\nreturn Sizzle;\n\n})( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\n\n// Deprecated\njQuery.expr[ \":\" ] = jQuery.expr.pseudos;\njQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\njQuery.escapeSelector = Sizzle.escape;\n\n\n\n\nvar dir = function( elem, dir, until ) {\n\tvar matched = [],\n\t\ttruncate = until !== undefined;\n\n\twhile ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmatched.push( elem );\n\t\t}\n\t}\n\treturn matched;\n};\n\n\nvar siblings = function( n, elem ) {\n\tvar matched = [];\n\n\tfor ( ; n; n = n.nextSibling ) {\n\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\tmatched.push( n );\n\t\t}\n\t}\n\n\treturn matched;\n};\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\n\n\nfunction nodeName( elem, name ) {\n\n  return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\n};\nvar rsingleTag = ( /^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i );\n\n\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t} );\n\t}\n\n\t// Single element\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t} );\n\t}\n\n\t// Arraylike of elements (jQuery, arguments, Array)\n\tif ( typeof qualifier !== \"string\" ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not;\n\t\t} );\n\t}\n\n\t// Filtered directly for both simple and complex selectors\n\treturn jQuery.filter( qualifier, elements, not );\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\tif ( elems.length === 1 && elem.nodeType === 1 ) {\n\t\treturn jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];\n\t}\n\n\treturn jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\treturn elem.nodeType === 1;\n\t} ) );\n};\n\njQuery.fn.extend( {\n\tfind: function( selector ) {\n\t\tvar i, ret,\n\t\t\tlen = this.length,\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter( function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} ) );\n\t\t}\n\n\t\tret = this.pushStack( [] );\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\treturn len > 1 ? jQuery.uniqueSort( ret ) : ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], false ) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], true ) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n} );\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\t// Shortcut simple #id case for speed\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/,\n\n\tinit = jQuery.fn.init = function( selector, context, root ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Method init() accepts an alternate rootjQuery\n\t\t// so migrate can support jQuery.sub (gh-2101)\n\t\troot = root || rootjQuery;\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[ 0 ] === \"<\" &&\n\t\t\t\tselector[ selector.length - 1 ] === \">\" &&\n\t\t\t\tselector.length >= 3 ) {\n\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && ( match[ 1 ] || !context ) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[ 1 ] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[ 0 ] : context;\n\n\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[ 1 ],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[ 2 ] );\n\n\t\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis[ 0 ] = elem;\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || root ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis[ 0 ] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( isFunction( selector ) ) {\n\t\t\treturn root.ready !== undefined ?\n\t\t\t\troot.ready( selector ) :\n\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\n\t// Methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend( {\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter( function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[ i ] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\ttargets = typeof selectors !== \"string\" && jQuery( selectors );\n\n\t\t// Positional selectors never match, since there's no _selection_ context\n\t\tif ( !rneedsContext.test( selectors ) ) {\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tfor ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {\n\n\t\t\t\t\t// Always skip document fragments\n\t\t\t\t\tif ( cur.nodeType < 11 && ( targets ?\n\t\t\t\t\t\ttargets.index( cur ) > -1 :\n\n\t\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\t\tjQuery.find.matchesSelector( cur, selectors ) ) ) {\n\n\t\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within the set\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// Index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.uniqueSort(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t}\n} );\n\nfunction sibling( cur, dir ) {\n\twhile ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}\n\treturn cur;\n}\n\njQuery.each( {\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn siblings( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn siblings( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\tif ( typeof elem.contentDocument !== \"undefined\" ) {\n\t\t\treturn elem.contentDocument;\n\t\t}\n\n\t\t// Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only\n\t\t// Treat the template element as a regular one in browsers that\n\t\t// don't support it.\n\t\tif ( nodeName( elem, \"template\" ) ) {\n\t\t\telem = elem.content || elem;\n\t\t}\n\n\t\treturn jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.uniqueSort( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n} );\nvar rnothtmlwhite = ( /[^\\x20\\t\\r\\n\\f]+/g );\n\n\n\n// Convert String-formatted options into Object-formatted ones\nfunction createOptions( options ) {\n\tvar object = {};\n\tjQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t} );\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\tcreateOptions( options ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\n\t\t// Last fire value for non-forgettable lists\n\t\tmemory,\n\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\n\t\t// Flag to prevent firing\n\t\tlocked,\n\n\t\t// Actual callback list\n\t\tlist = [],\n\n\t\t// Queue of execution data for repeatable lists\n\t\tqueue = [],\n\n\t\t// Index of currently firing callback (modified by add/remove as needed)\n\t\tfiringIndex = -1,\n\n\t\t// Fire callbacks\n\t\tfire = function() {\n\n\t\t\t// Enforce single-firing\n\t\t\tlocked = locked || options.once;\n\n\t\t\t// Execute callbacks for all pending executions,\n\t\t\t// respecting firingIndex overrides and runtime changes\n\t\t\tfired = firing = true;\n\t\t\tfor ( ; queue.length; firingIndex = -1 ) {\n\t\t\t\tmemory = queue.shift();\n\t\t\t\twhile ( ++firingIndex < list.length ) {\n\n\t\t\t\t\t// Run callback and check for early termination\n\t\t\t\t\tif ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&\n\t\t\t\t\t\toptions.stopOnFalse ) {\n\n\t\t\t\t\t\t// Jump to end and forget the data so .add doesn't re-fire\n\t\t\t\t\t\tfiringIndex = list.length;\n\t\t\t\t\t\tmemory = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Forget the data if we're done with it\n\t\t\tif ( !options.memory ) {\n\t\t\t\tmemory = false;\n\t\t\t}\n\n\t\t\tfiring = false;\n\n\t\t\t// Clean up if we're done firing for good\n\t\t\tif ( locked ) {\n\n\t\t\t\t// Keep an empty list if we have data for future add calls\n\t\t\t\tif ( memory ) {\n\t\t\t\t\tlist = [];\n\n\t\t\t\t// Otherwise, this object is spent\n\t\t\t\t} else {\n\t\t\t\t\tlist = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Actual Callbacks object\n\t\tself = {\n\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\n\t\t\t\t\t// If we have memory from a past run, we should fire after adding\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfiringIndex = list.length - 1;\n\t\t\t\t\t\tqueue.push( memory );\n\t\t\t\t\t}\n\n\t\t\t\t\t( function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tif ( isFunction( arg ) ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && toType( arg ) !== \"string\" ) {\n\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\t\t\t\t\t} )( arguments );\n\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\tvar index;\n\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\tlist.splice( index, 1 );\n\n\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ?\n\t\t\t\t\tjQuery.inArray( fn, list ) > -1 :\n\t\t\t\t\tlist.length > 0;\n\t\t\t},\n\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Disable .fire and .add\n\t\t\t// Abort any current/pending executions\n\t\t\t// Clear all callbacks and values\n\t\t\tdisable: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tlist = memory = \"\";\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\n\t\t\t// Disable .fire\n\t\t\t// Also disable .add unless we have memory (since it would have no effect)\n\t\t\t// Abort any pending executions\n\t\t\tlock: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tif ( !memory && !firing ) {\n\t\t\t\t\tlist = memory = \"\";\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tlocked: function() {\n\t\t\t\treturn !!locked;\n\t\t\t},\n\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( !locked ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tqueue.push( args );\n\t\t\t\t\tif ( !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\nfunction Identity( v ) {\n\treturn v;\n}\nfunction Thrower( ex ) {\n\tthrow ex;\n}\n\nfunction adoptValue( value, resolve, reject, noValue ) {\n\tvar method;\n\n\ttry {\n\n\t\t// Check for promise aspect first to privilege synchronous behavior\n\t\tif ( value && isFunction( ( method = value.promise ) ) ) {\n\t\t\tmethod.call( value ).done( resolve ).fail( reject );\n\n\t\t// Other thenables\n\t\t} else if ( value && isFunction( ( method = value.then ) ) ) {\n\t\t\tmethod.call( value, resolve, reject );\n\n\t\t// Other non-thenables\n\t\t} else {\n\n\t\t\t// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:\n\t\t\t// * false: [ value ].slice( 0 ) => resolve( value )\n\t\t\t// * true: [ value ].slice( 1 ) => resolve()\n\t\t\tresolve.apply( undefined, [ value ].slice( noValue ) );\n\t\t}\n\n\t// For Promises/A+, convert exceptions into rejections\n\t// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in\n\t// Deferred#then to conditionally suppress rejection.\n\t} catch ( value ) {\n\n\t\t// Support: Android 4.0 only\n\t\t// Strict mode functions invoked without .call/.apply get global-object context\n\t\treject.apply( undefined, [ value ] );\n\t}\n}\n\njQuery.extend( {\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\n\t\t\t\t// action, add listener, callbacks,\n\t\t\t\t// ... .then handlers, argument index, [final state]\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks( \"memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"memory\" ), 2 ],\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 0, \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 1, \"rejected\" ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\t\"catch\": function( fn ) {\n\t\t\t\t\treturn promise.then( null, fn );\n\t\t\t\t},\n\n\t\t\t\t// Keep pipe for back-compat\n\t\t\t\tpipe: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\n\t\t\t\t\t\t\t// Map tuples (progress, done, fail) to arguments (done, fail, progress)\n\t\t\t\t\t\t\tvar fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];\n\n\t\t\t\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\t\t\t\t// deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\n\t\t\t\t\t\t\tdeferred[ tuple[ 1 ] ]( function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify )\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\t\t\t\tthen: function( onFulfilled, onRejected, onProgress ) {\n\t\t\t\t\tvar maxDepth = 0;\n\t\t\t\t\tfunction resolve( depth, deferred, handler, special ) {\n\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\tvar that = this,\n\t\t\t\t\t\t\t\targs = arguments,\n\t\t\t\t\t\t\t\tmightThrow = function() {\n\t\t\t\t\t\t\t\t\tvar returned, then;\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.3\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-59\n\t\t\t\t\t\t\t\t\t// Ignore double-resolution attempts\n\t\t\t\t\t\t\t\t\tif ( depth < maxDepth ) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturned = handler.apply( that, args );\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.1\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-48\n\t\t\t\t\t\t\t\t\tif ( returned === deferred.promise() ) {\n\t\t\t\t\t\t\t\t\t\tthrow new TypeError( \"Thenable self-resolution\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ sections 2.3.3.1, 3.5\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-54\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-75\n\t\t\t\t\t\t\t\t\t// Retrieve `then` only once\n\t\t\t\t\t\t\t\t\tthen = returned &&\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.4\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-64\n\t\t\t\t\t\t\t\t\t\t// Only check objects and functions for thenability\n\t\t\t\t\t\t\t\t\t\t( typeof returned === \"object\" ||\n\t\t\t\t\t\t\t\t\t\t\ttypeof returned === \"function\" ) &&\n\t\t\t\t\t\t\t\t\t\treturned.then;\n\n\t\t\t\t\t\t\t\t\t// Handle a returned thenable\n\t\t\t\t\t\t\t\t\tif ( isFunction( then ) ) {\n\n\t\t\t\t\t\t\t\t\t\t// Special processors (notify) just wait for resolution\n\t\t\t\t\t\t\t\t\t\tif ( special ) {\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special )\n\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t// Normal processors (resolve) also hook into progress\n\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t// ...and disregard older resolution values\n\t\t\t\t\t\t\t\t\t\t\tmaxDepth++;\n\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdeferred.notifyWith )\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Handle all other returned values\n\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\tif ( handler !== Identity ) {\n\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\targs = [ returned ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Process the value(s)\n\t\t\t\t\t\t\t\t\t\t// Default process is resolve\n\t\t\t\t\t\t\t\t\t\t( special || deferred.resolveWith )( that, args );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t// Only normal processors (resolve) catch and reject exceptions\n\t\t\t\t\t\t\t\tprocess = special ?\n\t\t\t\t\t\t\t\t\tmightThrow :\n\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tmightThrow();\n\t\t\t\t\t\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t\t\t\t\t\tif ( jQuery.Deferred.exceptionHook ) {\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery.Deferred.exceptionHook( e,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprocess.stackTrace );\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.4.1\n\t\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-61\n\t\t\t\t\t\t\t\t\t\t\t// Ignore post-resolution exceptions\n\t\t\t\t\t\t\t\t\t\t\tif ( depth + 1 >= maxDepth ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\t\t\tif ( handler !== Thrower ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\t\t\targs = [ e ];\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tdeferred.rejectWith( that, args );\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.1\n\t\t\t\t\t\t\t// https://promisesaplus.com/#point-57\n\t\t\t\t\t\t\t// Re-resolve promises immediately to dodge false rejection from\n\t\t\t\t\t\t\t// subsequent errors\n\t\t\t\t\t\t\tif ( depth ) {\n\t\t\t\t\t\t\t\tprocess();\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// Call an optional hook to record the stack, in case of exception\n\t\t\t\t\t\t\t\t// since it's otherwise lost when execution goes async\n\t\t\t\t\t\t\t\tif ( jQuery.Deferred.getStackHook ) {\n\t\t\t\t\t\t\t\t\tprocess.stackTrace = jQuery.Deferred.getStackHook();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twindow.setTimeout( process );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\n\t\t\t\t\t\t// progress_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 0 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onProgress ) ?\n\t\t\t\t\t\t\t\t\tonProgress :\n\t\t\t\t\t\t\t\t\tIdentity,\n\t\t\t\t\t\t\t\tnewDefer.notifyWith\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// fulfilled_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 1 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onFulfilled ) ?\n\t\t\t\t\t\t\t\t\tonFulfilled :\n\t\t\t\t\t\t\t\t\tIdentity\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// rejected_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 2 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onRejected ) ?\n\t\t\t\t\t\t\t\t\tonRejected :\n\t\t\t\t\t\t\t\t\tThrower\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 5 ];\n\n\t\t\t// promise.progress = list.add\n\t\t\t// promise.done = list.add\n\t\t\t// promise.fail = list.add\n\t\t\tpromise[ tuple[ 1 ] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(\n\t\t\t\t\tfunction() {\n\n\t\t\t\t\t\t// state = \"resolved\" (i.e., fulfilled)\n\t\t\t\t\t\t// state = \"rejected\"\n\t\t\t\t\t\tstate = stateString;\n\t\t\t\t\t},\n\n\t\t\t\t\t// rejected_callbacks.disable\n\t\t\t\t\t// fulfilled_callbacks.disable\n\t\t\t\t\ttuples[ 3 - i ][ 2 ].disable,\n\n\t\t\t\t\t// rejected_handlers.disable\n\t\t\t\t\t// fulfilled_handlers.disable\n\t\t\t\t\ttuples[ 3 - i ][ 3 ].disable,\n\n\t\t\t\t\t// progress_callbacks.lock\n\t\t\t\t\ttuples[ 0 ][ 2 ].lock,\n\n\t\t\t\t\t// progress_handlers.lock\n\t\t\t\t\ttuples[ 0 ][ 3 ].lock\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// progress_handlers.fire\n\t\t\t// fulfilled_handlers.fire\n\t\t\t// rejected_handlers.fire\n\t\t\tlist.add( tuple[ 3 ].fire );\n\n\t\t\t// deferred.notify = function() { deferred.notifyWith(...) }\n\t\t\t// deferred.resolve = function() { deferred.resolveWith(...) }\n\t\t\t// deferred.reject = function() { deferred.rejectWith(...) }\n\t\t\tdeferred[ tuple[ 0 ] ] = function() {\n\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ]( this === deferred ? undefined : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\n\t\t\t// deferred.notifyWith = list.fireWith\n\t\t\t// deferred.resolveWith = list.fireWith\n\t\t\t// deferred.rejectWith = list.fireWith\n\t\t\tdeferred[ tuple[ 0 ] + \"With\" ] = list.fireWith;\n\t\t} );\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( singleValue ) {\n\t\tvar\n\n\t\t\t// count of uncompleted subordinates\n\t\t\tremaining = arguments.length,\n\n\t\t\t// count of unprocessed arguments\n\t\t\ti = remaining,\n\n\t\t\t// subordinate fulfillment data\n\t\t\tresolveContexts = Array( i ),\n\t\t\tresolveValues = slice.call( arguments ),\n\n\t\t\t// the master Deferred\n\t\t\tmaster = jQuery.Deferred(),\n\n\t\t\t// subordinate callback factory\n\t\t\tupdateFunc = function( i ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tresolveContexts[ i ] = this;\n\t\t\t\t\tresolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( !( --remaining ) ) {\n\t\t\t\t\t\tmaster.resolveWith( resolveContexts, resolveValues );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\n\t\t// Single- and empty arguments are adopted like Promise.resolve\n\t\tif ( remaining <= 1 ) {\n\t\t\tadoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,\n\t\t\t\t!remaining );\n\n\t\t\t// Use .then() to unwrap secondary thenables (cf. gh-3000)\n\t\t\tif ( master.state() === \"pending\" ||\n\t\t\t\tisFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {\n\n\t\t\t\treturn master.then();\n\t\t\t}\n\t\t}\n\n\t\t// Multiple arguments are aggregated like Promise.all array elements\n\t\twhile ( i-- ) {\n\t\t\tadoptValue( resolveValues[ i ], updateFunc( i ), master.reject );\n\t\t}\n\n\t\treturn master.promise();\n\t}\n} );\n\n\n// These usually indicate a programmer mistake during development,\n// warn about them ASAP rather than swallowing them by default.\nvar rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;\n\njQuery.Deferred.exceptionHook = function( error, stack ) {\n\n\t// Support: IE 8 - 9 only\n\t// Console exists when dev tools are open, which can happen at any time\n\tif ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {\n\t\twindow.console.warn( \"jQuery.Deferred exception: \" + error.message, error.stack, stack );\n\t}\n};\n\n\n\n\njQuery.readyException = function( error ) {\n\twindow.setTimeout( function() {\n\t\tthrow error;\n\t} );\n};\n\n\n\n\n// The deferred used on DOM ready\nvar readyList = jQuery.Deferred();\n\njQuery.fn.ready = function( fn ) {\n\n\treadyList\n\t\t.then( fn )\n\n\t\t// Wrap jQuery.readyException in a function so that the lookup\n\t\t// happens at the time of error handling instead of callback\n\t\t// registration.\n\t\t.catch( function( error ) {\n\t\t\tjQuery.readyException( error );\n\t\t} );\n\n\treturn this;\n};\n\njQuery.extend( {\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\t}\n} );\n\njQuery.ready.then = readyList.then;\n\n// The ready event handler and self cleanup method\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed );\n\twindow.removeEventListener( \"load\", completed );\n\tjQuery.ready();\n}\n\n// Catch cases where $(document).ready() is called\n// after the browser event has already occurred.\n// Support: IE <=9 - 10 only\n// Older IE sometimes signals \"interactive\" too soon\nif ( document.readyState === \"complete\" ||\n\t( document.readyState !== \"loading\" && !document.documentElement.doScroll ) ) {\n\n\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\twindow.setTimeout( jQuery.ready );\n\n} else {\n\n\t// Use the handy event callback\n\tdocument.addEventListener( \"DOMContentLoaded\", completed );\n\n\t// A fallback to window.onload, that will always work\n\twindow.addEventListener( \"load\", completed );\n}\n\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( toType( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\taccess( elems, fn, i, key[ i ], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tfn(\n\t\t\t\t\telems[ i ], key, raw ?\n\t\t\t\t\tvalue :\n\t\t\t\t\tvalue.call( elems[ i ], i, fn( elems[ i ], key ) )\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( chainable ) {\n\t\treturn elems;\n\t}\n\n\t// Gets\n\tif ( bulk ) {\n\t\treturn fn.call( elems );\n\t}\n\n\treturn len ? fn( elems[ 0 ], key ) : emptyGet;\n};\n\n\n// Matches dashed string for camelizing\nvar rmsPrefix = /^-ms-/,\n\trdashAlpha = /-([a-z])/g;\n\n// Used by camelCase as callback to replace()\nfunction fcamelCase( all, letter ) {\n\treturn letter.toUpperCase();\n}\n\n// Convert dashed to camelCase; used by the css and data modules\n// Support: IE <=9 - 11, Edge 12 - 15\n// Microsoft forgot to hump their vendor prefix (#9572)\nfunction camelCase( string ) {\n\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n}\nvar acceptData = function( owner ) {\n\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\n\n\nfunction Data() {\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\n\nData.prototype = {\n\n\tcache: function( owner ) {\n\n\t\t// Check if the owner object already has a cache\n\t\tvar value = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !value ) {\n\t\t\tvalue = {};\n\n\t\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t\t// but we should not, see #8335.\n\t\t\t// Always return an empty object.\n\t\t\tif ( acceptData( owner ) ) {\n\n\t\t\t\t// If it is a node unlikely to be stringify-ed or looped over\n\t\t\t\t// use plain assignment\n\t\t\t\tif ( owner.nodeType ) {\n\t\t\t\t\towner[ this.expando ] = value;\n\n\t\t\t\t// Otherwise secure it in a non-enumerable property\n\t\t\t\t// configurable must be true to allow the property to be\n\t\t\t\t// deleted when data is removed\n\t\t\t\t} else {\n\t\t\t\t\tObject.defineProperty( owner, this.expando, {\n\t\t\t\t\t\tvalue: value,\n\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn value;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\tcache = this.cache( owner );\n\n\t\t// Handle: [ owner, key, value ] args\n\t\t// Always use camelCase key (gh-2257)\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ camelCase( data ) ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\n\t\t\t// Copy the properties one-by-one to the cache object\n\t\t\tfor ( prop in data ) {\n\t\t\t\tcache[ camelCase( prop ) ] = data[ prop ];\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\treturn key === undefined ?\n\t\t\tthis.cache( owner ) :\n\n\t\t\t// Always use camelCase key (gh-2257)\n\t\t\towner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];\n\t},\n\taccess: function( owner, key, value ) {\n\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t( ( key && typeof key === \"string\" ) && value === undefined ) ) {\n\n\t\t\treturn this.get( owner, key );\n\t\t}\n\n\t\t// When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i,\n\t\t\tcache = owner[ this.expando ];\n\n\t\tif ( cache === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key !== undefined ) {\n\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( Array.isArray( key ) ) {\n\n\t\t\t\t// If key is an array of keys...\n\t\t\t\t// We always set camelCase keys, so remove that.\n\t\t\t\tkey = key.map( camelCase );\n\t\t\t} else {\n\t\t\t\tkey = camelCase( key );\n\n\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\tkey = key in cache ?\n\t\t\t\t\t[ key ] :\n\t\t\t\t\t( key.match( rnothtmlwhite ) || [] );\n\t\t\t}\n\n\t\t\ti = key.length;\n\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ key[ i ] ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if there's no more data\n\t\tif ( key === undefined || jQuery.isEmptyObject( cache ) ) {\n\n\t\t\t// Support: Chrome <=35 - 45\n\t\t\t// Webkit & Blink performance suffers when deleting properties\n\t\t\t// from DOM nodes, so set to undefined instead\n\t\t\t// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)\n\t\t\tif ( owner.nodeType ) {\n\t\t\t\towner[ this.expando ] = undefined;\n\t\t\t} else {\n\t\t\t\tdelete owner[ this.expando ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\tvar cache = owner[ this.expando ];\n\t\treturn cache !== undefined && !jQuery.isEmptyObject( cache );\n\t}\n};\nvar dataPriv = new Data();\n\nvar dataUser = new Data();\n\n\n\n//\tImplementation Summary\n//\n//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n//\t2. Improve the module's maintainability by reducing the storage\n//\t\tpaths to a single mechanism.\n//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /[A-Z]/g;\n\nfunction getData( data ) {\n\tif ( data === \"true\" ) {\n\t\treturn true;\n\t}\n\n\tif ( data === \"false\" ) {\n\t\treturn false;\n\t}\n\n\tif ( data === \"null\" ) {\n\t\treturn null;\n\t}\n\n\t// Only convert to a number if it doesn't change the string\n\tif ( data === +data + \"\" ) {\n\t\treturn +data;\n\t}\n\n\tif ( rbrace.test( data ) ) {\n\t\treturn JSON.parse( data );\n\t}\n\n\treturn data;\n}\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$&\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = getData( data );\n\t\t\t} catch ( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdataUser.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend( {\n\thasData: function( elem ) {\n\t\treturn dataUser.hasData( elem ) || dataPriv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn dataUser.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdataUser.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to dataPriv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn dataPriv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdataPriv.remove( elem, name );\n\t}\n} );\n\njQuery.fn.extend( {\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = dataUser.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !dataPriv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE 11 only\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = camelCase( name.slice( 5 ) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdataPriv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tdataUser.set( this, key );\n\t\t\t} );\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data;\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// The key will always be camelCased in Data\n\t\t\t\tdata = dataUser.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each( function() {\n\n\t\t\t\t// We always store the camelCased key\n\t\t\t\tdataUser.set( this, key, value );\n\t\t\t} );\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each( function() {\n\t\t\tdataUser.remove( this, key );\n\t\t} );\n\t}\n} );\n\n\njQuery.extend( {\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = dataPriv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || Array.isArray( data ) ) {\n\t\t\t\t\tqueue = dataPriv.access( elem, type, jQuery.makeArray( data ) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// Clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// Not public - generate a queueHooks object, or return the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn dataPriv.get( elem, key ) || dataPriv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks( \"once memory\" ).add( function() {\n\t\t\t\tdataPriv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t} )\n\t\t} );\n\t}\n} );\n\njQuery.fn.extend( {\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[ 0 ], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each( function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[ 0 ] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t} );\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t} );\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = dataPriv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n} );\nvar pnum = ( /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/ ).source;\n\nvar rcssNum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" );\n\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar documentElement = document.documentElement;\n\n\n\n\tvar isAttached = function( elem ) {\n\t\t\treturn jQuery.contains( elem.ownerDocument, elem );\n\t\t},\n\t\tcomposed = { composed: true };\n\n\t// Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only\n\t// Check attachment across shadow DOM boundaries when possible (gh-3504)\n\t// Support: iOS 10.0-10.2 only\n\t// Early iOS 10 versions support `attachShadow` but not `getRootNode`,\n\t// leading to errors. We need to check for `getRootNode`.\n\tif ( documentElement.getRootNode ) {\n\t\tisAttached = function( elem ) {\n\t\t\treturn jQuery.contains( elem.ownerDocument, elem ) ||\n\t\t\t\telem.getRootNode( composed ) === elem.ownerDocument;\n\t\t};\n\t}\nvar isHiddenWithinTree = function( elem, el ) {\n\n\t\t// isHiddenWithinTree might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\n\t\t// Inline style trumps all\n\t\treturn elem.style.display === \"none\" ||\n\t\t\telem.style.display === \"\" &&\n\n\t\t\t// Otherwise, check computed style\n\t\t\t// Support: Firefox <=43 - 45\n\t\t\t// Disconnected elements can have computed display: none, so first confirm that elem is\n\t\t\t// in the document.\n\t\t\tisAttached( elem ) &&\n\n\t\t\tjQuery.css( elem, \"display\" ) === \"none\";\n\t};\n\nvar swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\n\n\nfunction adjustCSS( elem, prop, valueParts, tween ) {\n\tvar adjusted, scale,\n\t\tmaxIterations = 20,\n\t\tcurrentValue = tween ?\n\t\t\tfunction() {\n\t\t\t\treturn tween.cur();\n\t\t\t} :\n\t\t\tfunction() {\n\t\t\t\treturn jQuery.css( elem, prop, \"\" );\n\t\t\t},\n\t\tinitial = currentValue(),\n\t\tunit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t// Starting value computation is required for potential unit mismatches\n\t\tinitialInUnit = elem.nodeType &&\n\t\t\t( jQuery.cssNumber[ prop ] || unit !== \"px\" && +initial ) &&\n\t\t\trcssNum.exec( jQuery.css( elem, prop ) );\n\n\tif ( initialInUnit && initialInUnit[ 3 ] !== unit ) {\n\n\t\t// Support: Firefox <=54\n\t\t// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)\n\t\tinitial = initial / 2;\n\n\t\t// Trust units reported by jQuery.css\n\t\tunit = unit || initialInUnit[ 3 ];\n\n\t\t// Iteratively approximate from a nonzero starting point\n\t\tinitialInUnit = +initial || 1;\n\n\t\twhile ( maxIterations-- ) {\n\n\t\t\t// Evaluate and update our best guess (doubling guesses that zero out).\n\t\t\t// Finish if the scale equals or crosses 1 (making the old*new product non-positive).\n\t\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\t\t\tif ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {\n\t\t\t\tmaxIterations = 0;\n\t\t\t}\n\t\t\tinitialInUnit = initialInUnit / scale;\n\n\t\t}\n\n\t\tinitialInUnit = initialInUnit * 2;\n\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\n\t\t// Make sure we update the tween properties later on\n\t\tvalueParts = valueParts || [];\n\t}\n\n\tif ( valueParts ) {\n\t\tinitialInUnit = +initialInUnit || +initial || 0;\n\n\t\t// Apply relative offset (+=/-=) if specified\n\t\tadjusted = valueParts[ 1 ] ?\n\t\t\tinitialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :\n\t\t\t+valueParts[ 2 ];\n\t\tif ( tween ) {\n\t\t\ttween.unit = unit;\n\t\t\ttween.start = initialInUnit;\n\t\t\ttween.end = adjusted;\n\t\t}\n\t}\n\treturn adjusted;\n}\n\n\nvar defaultDisplayMap = {};\n\nfunction getDefaultDisplay( elem ) {\n\tvar temp,\n\t\tdoc = elem.ownerDocument,\n\t\tnodeName = elem.nodeName,\n\t\tdisplay = defaultDisplayMap[ nodeName ];\n\n\tif ( display ) {\n\t\treturn display;\n\t}\n\n\ttemp = doc.body.appendChild( doc.createElement( nodeName ) );\n\tdisplay = jQuery.css( temp, \"display\" );\n\n\ttemp.parentNode.removeChild( temp );\n\n\tif ( display === \"none\" ) {\n\t\tdisplay = \"block\";\n\t}\n\tdefaultDisplayMap[ nodeName ] = display;\n\n\treturn display;\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\t// Determine new display value for elements that need to change\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\n\t\t\t// Since we force visibility upon cascade-hidden elements, an immediate (and slow)\n\t\t\t// check is required in this first loop unless we have a nonempty display value (either\n\t\t\t// inline or about-to-be-restored)\n\t\t\tif ( display === \"none\" ) {\n\t\t\t\tvalues[ index ] = dataPriv.get( elem, \"display\" ) || null;\n\t\t\t\tif ( !values[ index ] ) {\n\t\t\t\t\telem.style.display = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( elem.style.display === \"\" && isHiddenWithinTree( elem ) ) {\n\t\t\t\tvalues[ index ] = getDefaultDisplay( elem );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( display !== \"none\" ) {\n\t\t\t\tvalues[ index ] = \"none\";\n\n\t\t\t\t// Remember what we're overwriting\n\t\t\t\tdataPriv.set( elem, \"display\", display );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of the elements in a second loop to avoid constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\tif ( values[ index ] != null ) {\n\t\t\telements[ index ].style.display = values[ index ];\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend( {\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tif ( isHiddenWithinTree( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t} );\n\t}\n} );\nvar rcheckableType = ( /^(?:checkbox|radio)$/i );\n\nvar rtagName = ( /<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)/i );\n\nvar rscriptType = ( /^$|^module$|\\/(?:java|ecma)script/i );\n\n\n\n// We have to close these tags to support XHTML (#13200)\nvar wrapMap = {\n\n\t// Support: IE <=9 only\n\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t// XHTML parsers do not magically insert elements in the\n\t// same way that tag soup parsers do. So we cannot shorten\n\t// this by omitting <tbody> or other required elements.\n\tthead: [ 1, \"<table>\", \"</table>\" ],\n\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t_default: [ 0, \"\", \"\" ]\n};\n\n// Support: IE <=9 only\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n\nfunction getAll( context, tag ) {\n\n\t// Support: IE <=9 - 11 only\n\t// Use typeof to avoid zero-argument method invocation on host objects (#15151)\n\tvar ret;\n\n\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\tret = context.getElementsByTagName( tag || \"*\" );\n\n\t} else if ( typeof context.querySelectorAll !== \"undefined\" ) {\n\t\tret = context.querySelectorAll( tag || \"*\" );\n\n\t} else {\n\t\tret = [];\n\t}\n\n\tif ( tag === undefined || tag && nodeName( context, tag ) ) {\n\t\treturn jQuery.merge( [ context ], ret );\n\t}\n\n\treturn ret;\n}\n\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdataPriv.set(\n\t\t\telems[ i ],\n\t\t\t\"globalEval\",\n\t\t\t!refElements || dataPriv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\n\nvar rhtml = /<|&#?\\w+;/;\n\nfunction buildFragment( elems, context, scripts, selection, ignored ) {\n\tvar elem, tmp, tag, wrap, attached, j,\n\t\tfragment = context.createDocumentFragment(),\n\t\tnodes = [],\n\t\ti = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\telem = elems[ i ];\n\n\t\tif ( elem || elem === 0 ) {\n\n\t\t\t// Add nodes directly\n\t\t\tif ( toType( elem ) === \"object\" ) {\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t// Convert non-html into a text node\n\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t// Convert html into DOM nodes\n\t\t\t} else {\n\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement( \"div\" ) );\n\n\t\t\t\t// Deserialize a standard representation\n\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\ttmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];\n\n\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\tj = wrap[ 0 ];\n\t\t\t\twhile ( j-- ) {\n\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t}\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t// Remember the top-level container\n\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\ttmp.textContent = \"\";\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove wrapper from fragment\n\tfragment.textContent = \"\";\n\n\ti = 0;\n\twhile ( ( elem = nodes[ i++ ] ) ) {\n\n\t\t// Skip elements already in the context collection (trac-4087)\n\t\tif ( selection && jQuery.inArray( elem, selection ) > -1 ) {\n\t\t\tif ( ignored ) {\n\t\t\t\tignored.push( elem );\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tattached = isAttached( elem );\n\n\t\t// Append to fragment\n\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t// Preserve script evaluation history\n\t\tif ( attached ) {\n\t\t\tsetGlobalEval( tmp );\n\t\t}\n\n\t\t// Capture executables\n\t\tif ( scripts ) {\n\t\t\tj = 0;\n\t\t\twhile ( ( elem = tmp[ j++ ] ) ) {\n\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\tscripts.push( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fragment;\n}\n\n\n( function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Support: Android 4.0 - 4.3 only\n\t// Check state lost if the name is set (#11217)\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Android <=4.1 only\n\t// Older WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE <=11 only\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n} )();\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n// Support: IE <=9 - 11+\n// focus() and blur() are asynchronous, except when they are no-op.\n// So expect focus to be synchronous when the element is already active,\n// and blur to be synchronous when the element is not already active.\n// (focus and blur are always synchronous in other supported browsers,\n// this just defines when we can count on it).\nfunction expectSync( elem, type ) {\n\treturn ( elem === safeActiveElement() ) === ( type === \"focus\" );\n}\n\n// Support: IE <=9 only\n// Accessing document.activeElement can throw unexpectedly\n// https://bugs.jquery.com/ticket/13393\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\nfunction on( elem, types, selector, data, fn, one ) {\n\tvar origFn, type;\n\n\t// Types can be a map of types/handlers\n\tif ( typeof types === \"object\" ) {\n\n\t\t// ( types-Object, selector, data )\n\t\tif ( typeof selector !== \"string\" ) {\n\n\t\t\t// ( types-Object, data )\n\t\t\tdata = data || selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tfor ( type in types ) {\n\t\t\ton( elem, type, selector, data, types[ type ], one );\n\t\t}\n\t\treturn elem;\n\t}\n\n\tif ( data == null && fn == null ) {\n\n\t\t// ( types, fn )\n\t\tfn = selector;\n\t\tdata = selector = undefined;\n\t} else if ( fn == null ) {\n\t\tif ( typeof selector === \"string\" ) {\n\n\t\t\t// ( types, selector, fn )\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t} else {\n\n\t\t\t// ( types, data, fn )\n\t\t\tfn = data;\n\t\t\tdata = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t}\n\tif ( fn === false ) {\n\t\tfn = returnFalse;\n\t} else if ( !fn ) {\n\t\treturn elem;\n\t}\n\n\tif ( one === 1 ) {\n\t\torigFn = fn;\n\t\tfn = function( event ) {\n\n\t\t\t// Can use an empty set, since event contains the info\n\t\t\tjQuery().off( event );\n\t\t\treturn origFn.apply( this, arguments );\n\t\t};\n\n\t\t// Use same guid so caller can remove using origFn\n\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t}\n\treturn elem.each( function() {\n\t\tjQuery.event.add( this, types, fn, data, selector );\n\t} );\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.get( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Ensure that invalid selectors throw exceptions at attach time\n\t\t// Evaluate against documentElement in case elem is a non-element node (e.g., document)\n\t\tif ( selector ) {\n\t\t\tjQuery.find.matchesSelector( documentElement, selector );\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !( events = elemData.events ) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !( eventHandle = elemData.handle ) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend( {\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join( \".\" )\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !( handlers = events[ type ] ) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\tif ( !special.setup ||\n\t\t\t\t\tspecial.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.hasData( elem ) && dataPriv.get( elem );\n\n\t\tif ( !elemData || !( events = elemData.events ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[ 2 ] &&\n\t\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector ||\n\t\t\t\t\t\tselector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown ||\n\t\t\t\t\tspecial.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove data and the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdataPriv.remove( elem, \"handle events\" );\n\t\t}\n\t},\n\n\tdispatch: function( nativeEvent ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tvar event = jQuery.event.fix( nativeEvent );\n\n\t\tvar i, j, ret, matched, handleObj, handlerQueue,\n\t\t\targs = new Array( arguments.length ),\n\t\t\thandlers = ( dataPriv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[ 0 ] = event;\n\n\t\tfor ( i = 1; i < arguments.length; i++ ) {\n\t\t\targs[ i ] = arguments[ i ];\n\t\t}\n\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( ( handleObj = matched.handlers[ j++ ] ) &&\n\t\t\t\t!event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// If the event is namespaced, then each handler is only invoked if it is\n\t\t\t\t// specially universal or its namespaces are a superset of the event's.\n\t\t\t\tif ( !event.rnamespace || handleObj.namespace === false ||\n\t\t\t\t\tevent.rnamespace.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||\n\t\t\t\t\t\thandleObj.handler ).apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( ( event.result = ret ) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, handleObj, sel, matchedHandlers, matchedSelectors,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\tif ( delegateCount &&\n\n\t\t\t// Support: IE <=9\n\t\t\t// Black-hole SVG <use> instance trees (trac-13180)\n\t\t\tcur.nodeType &&\n\n\t\t\t// Support: Firefox <=42\n\t\t\t// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n\t\t\t// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n\t\t\t// Support: IE 11 only\n\t\t\t// ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n\t\t\t!( event.type === \"click\" && event.button >= 1 ) ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && !( event.type === \"click\" && cur.disabled === true ) ) {\n\t\t\t\t\tmatchedHandlers = [];\n\t\t\t\t\tmatchedSelectors = {};\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatchedSelectors[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) > -1 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] ) {\n\t\t\t\t\t\t\tmatchedHandlers.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matchedHandlers.length ) {\n\t\t\t\t\t\thandlerQueue.push( { elem: cur, handlers: matchedHandlers } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tcur = this;\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\taddProp: function( name, hook ) {\n\t\tObject.defineProperty( jQuery.Event.prototype, name, {\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\n\t\t\tget: isFunction( hook ) ?\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn hook( this.originalEvent );\n\t\t\t\t\t}\n\t\t\t\t} :\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn this.originalEvent[ name ];\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\tset: function( value ) {\n\t\t\t\tObject.defineProperty( this, name, {\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: value\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t},\n\n\tfix: function( originalEvent ) {\n\t\treturn originalEvent[ jQuery.expando ] ?\n\t\t\toriginalEvent :\n\t\t\tnew jQuery.Event( originalEvent );\n\t},\n\n\tspecial: {\n\t\tload: {\n\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tclick: {\n\n\t\t\t// Utilize native event to ensure correct state for checkable inputs\n\t\t\tsetup: function( data ) {\n\n\t\t\t\t// For mutual compressibility with _default, replace `this` access with a local var.\n\t\t\t\t// `|| data` is dead code meant only to preserve the variable through minification.\n\t\t\t\tvar el = this || data;\n\n\t\t\t\t// Claim the first handler\n\t\t\t\tif ( rcheckableType.test( el.type ) &&\n\t\t\t\t\tel.click && nodeName( el, \"input\" ) ) {\n\n\t\t\t\t\t// dataPriv.set( el, \"click\", ... )\n\t\t\t\t\tleverageNative( el, \"click\", returnTrue );\n\t\t\t\t}\n\n\t\t\t\t// Return false to allow normal processing in the caller\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\ttrigger: function( data ) {\n\n\t\t\t\t// For mutual compressibility with _default, replace `this` access with a local var.\n\t\t\t\t// `|| data` is dead code meant only to preserve the variable through minification.\n\t\t\t\tvar el = this || data;\n\n\t\t\t\t// Force setup before triggering a click\n\t\t\t\tif ( rcheckableType.test( el.type ) &&\n\t\t\t\t\tel.click && nodeName( el, \"input\" ) ) {\n\n\t\t\t\t\tleverageNative( el, \"click\" );\n\t\t\t\t}\n\n\t\t\t\t// Return non-false to allow normal event-path propagation\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, suppress native .click() on links\n\t\t\t// Also prevent it if we're currently inside a leveraged native-event stack\n\t\t\t_default: function( event ) {\n\t\t\t\tvar target = event.target;\n\t\t\t\treturn rcheckableType.test( target.type ) &&\n\t\t\t\t\ttarget.click && nodeName( target, \"input\" ) &&\n\t\t\t\t\tdataPriv.get( target, \"click\" ) ||\n\t\t\t\t\tnodeName( target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Ensure the presence of an event listener that handles manually-triggered\n// synthetic events by interrupting progress until reinvoked in response to\n// *native* events that it fires directly, ensuring that state changes have\n// already occurred before other listeners are invoked.\nfunction leverageNative( el, type, expectSync ) {\n\n\t// Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add\n\tif ( !expectSync ) {\n\t\tif ( dataPriv.get( el, type ) === undefined ) {\n\t\t\tjQuery.event.add( el, type, returnTrue );\n\t\t}\n\t\treturn;\n\t}\n\n\t// Register the controller as a special universal handler for all event namespaces\n\tdataPriv.set( el, type, false );\n\tjQuery.event.add( el, type, {\n\t\tnamespace: false,\n\t\thandler: function( event ) {\n\t\t\tvar notAsync, result,\n\t\t\t\tsaved = dataPriv.get( this, type );\n\n\t\t\tif ( ( event.isTrigger & 1 ) && this[ type ] ) {\n\n\t\t\t\t// Interrupt processing of the outer synthetic .trigger()ed event\n\t\t\t\t// Saved data should be false in such cases, but might be a leftover capture object\n\t\t\t\t// from an async native handler (gh-4350)\n\t\t\t\tif ( !saved.length ) {\n\n\t\t\t\t\t// Store arguments for use when handling the inner native event\n\t\t\t\t\t// There will always be at least one argument (an event object), so this array\n\t\t\t\t\t// will not be confused with a leftover capture object.\n\t\t\t\t\tsaved = slice.call( arguments );\n\t\t\t\t\tdataPriv.set( this, type, saved );\n\n\t\t\t\t\t// Trigger the native event and capture its result\n\t\t\t\t\t// Support: IE <=9 - 11+\n\t\t\t\t\t// focus() and blur() are asynchronous\n\t\t\t\t\tnotAsync = expectSync( this, type );\n\t\t\t\t\tthis[ type ]();\n\t\t\t\t\tresult = dataPriv.get( this, type );\n\t\t\t\t\tif ( saved !== result || notAsync ) {\n\t\t\t\t\t\tdataPriv.set( this, type, false );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = {};\n\t\t\t\t\t}\n\t\t\t\t\tif ( saved !== result ) {\n\n\t\t\t\t\t\t// Cancel the outer synthetic event\n\t\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\treturn result.value;\n\t\t\t\t\t}\n\n\t\t\t\t// If this is an inner synthetic event for an event with a bubbling surrogate\n\t\t\t\t// (focus or blur), assume that the surrogate already propagated from triggering the\n\t\t\t\t// native event and prevent that from happening again here.\n\t\t\t\t// This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the\n\t\t\t\t// bubbling surrogate propagates *after* the non-bubbling base), but that seems\n\t\t\t\t// less bad than duplication.\n\t\t\t\t} else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t}\n\n\t\t\t// If this is a native event triggered above, everything is now in order\n\t\t\t// Fire an inner synthetic event with the original arguments\n\t\t\t} else if ( saved.length ) {\n\n\t\t\t\t// ...and capture the result\n\t\t\t\tdataPriv.set( this, type, {\n\t\t\t\t\tvalue: jQuery.event.trigger(\n\n\t\t\t\t\t\t// Support: IE <=9 - 11+\n\t\t\t\t\t\t// Extend with the prototype to reset the above stopImmediatePropagation()\n\t\t\t\t\t\tjQuery.extend( saved[ 0 ], jQuery.Event.prototype ),\n\t\t\t\t\t\tsaved.slice( 1 ),\n\t\t\t\t\t\tthis\n\t\t\t\t\t)\n\t\t\t\t} );\n\n\t\t\t\t// Abort handling of the native event\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t}\n\t\t}\n\t} );\n}\n\njQuery.removeEvent = function( elem, type, handle ) {\n\n\t// This \"if\" is needed for plain objects\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\n\t// Allow instantiation without the 'new' keyword\n\tif ( !( this instanceof jQuery.Event ) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\n\t\t\t\t// Support: Android <=2.3 only\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t\t// Create target properties\n\t\t// Support: Safari <=6 - 7 only\n\t\t// Target should not be a text node (#504, #13143)\n\t\tthis.target = ( src.target && src.target.nodeType === 3 ) ?\n\t\t\tsrc.target.parentNode :\n\t\t\tsrc.target;\n\n\t\tthis.currentTarget = src.currentTarget;\n\t\tthis.relatedTarget = src.relatedTarget;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || Date.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tconstructor: jQuery.Event,\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\tisSimulated: false,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Includes all common event props including KeyEvent and MouseEvent specific props\njQuery.each( {\n\taltKey: true,\n\tbubbles: true,\n\tcancelable: true,\n\tchangedTouches: true,\n\tctrlKey: true,\n\tdetail: true,\n\teventPhase: true,\n\tmetaKey: true,\n\tpageX: true,\n\tpageY: true,\n\tshiftKey: true,\n\tview: true,\n\t\"char\": true,\n\tcode: true,\n\tcharCode: true,\n\tkey: true,\n\tkeyCode: true,\n\tbutton: true,\n\tbuttons: true,\n\tclientX: true,\n\tclientY: true,\n\toffsetX: true,\n\toffsetY: true,\n\tpointerId: true,\n\tpointerType: true,\n\tscreenX: true,\n\tscreenY: true,\n\ttargetTouches: true,\n\ttoElement: true,\n\ttouches: true,\n\n\twhich: function( event ) {\n\t\tvar button = event.button;\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && rkeyEvent.test( event.type ) ) {\n\t\t\treturn event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\tif ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {\n\t\t\tif ( button & 1 ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tif ( button & 2 ) {\n\t\t\t\treturn 3;\n\t\t\t}\n\n\t\t\tif ( button & 4 ) {\n\t\t\t\treturn 2;\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn event.which;\n\t}\n}, jQuery.event.addProp );\n\njQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( type, delegateType ) {\n\tjQuery.event.special[ type ] = {\n\n\t\t// Utilize native event if possible so blur/focus sequence is correct\n\t\tsetup: function() {\n\n\t\t\t// Claim the first handler\n\t\t\t// dataPriv.set( this, \"focus\", ... )\n\t\t\t// dataPriv.set( this, \"blur\", ... )\n\t\t\tleverageNative( this, type, expectSync );\n\n\t\t\t// Return false to allow normal processing in the caller\n\t\t\treturn false;\n\t\t},\n\t\ttrigger: function() {\n\n\t\t\t// Force setup before trigger\n\t\t\tleverageNative( this, type );\n\n\t\t\t// Return non-false to allow normal event-path propagation\n\t\t\treturn true;\n\t\t},\n\n\t\tdelegateType: delegateType\n\t};\n} );\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// so that event delegation works in jQuery.\n// Do the same for pointerenter/pointerleave and pointerover/pointerout\n//\n// Support: Safari 7 only\n// Safari sends mouseenter too often; see:\n// https://bugs.chromium.org/p/chromium/issues/detail?id=470258\n// for the description of the bug (it existed in older Chrome versions as well).\njQuery.each( {\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mouseenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n} );\n\njQuery.fn.extend( {\n\n\ton: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn );\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ?\n\t\t\t\t\thandleObj.origType + \".\" + handleObj.namespace :\n\t\t\t\t\thandleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t} );\n\t}\n} );\n\n\nvar\n\n\t/* eslint-disable max-len */\n\n\t// See https://github.com/eslint/eslint/issues/3229\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)[^>]*)\\/>/gi,\n\n\t/* eslint-enable */\n\n\t// Support: IE <=10 - 11, Edge 12 - 13 only\n\t// In IE/Edge using regex groups here causes severe slowdowns.\n\t// See https://connect.microsoft.com/IE/feedback/details/1736512/\n\trnoInnerhtml = /<script|<style|<link/i,\n\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g;\n\n// Prefer a tbody over its parent table for containing new rows\nfunction manipulationTarget( elem, content ) {\n\tif ( nodeName( elem, \"table\" ) &&\n\t\tnodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ) {\n\n\t\treturn jQuery( elem ).children( \"tbody\" )[ 0 ] || elem;\n\t}\n\n\treturn elem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = ( elem.getAttribute( \"type\" ) !== null ) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tif ( ( elem.type || \"\" ).slice( 0, 5 ) === \"true/\" ) {\n\t\telem.type = elem.type.slice( 5 );\n\t} else {\n\t\telem.removeAttribute( \"type\" );\n\t}\n\n\treturn elem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( dataPriv.hasData( src ) ) {\n\t\tpdataOld = dataPriv.access( src );\n\t\tpdataCur = dataPriv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( dataUser.hasData( src ) ) {\n\t\tudataOld = dataUser.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdataUser.set( dest, udataCur );\n\t}\n}\n\n// Fix IE bugs, see support tests\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\nfunction domManip( collection, args, callback, ignored ) {\n\n\t// Flatten any nested arrays\n\targs = concat.apply( [], args );\n\n\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\ti = 0,\n\t\tl = collection.length,\n\t\tiNoClone = l - 1,\n\t\tvalue = args[ 0 ],\n\t\tvalueIsFunction = isFunction( value );\n\n\t// We can't cloneNode fragments that contain checked, in WebKit\n\tif ( valueIsFunction ||\n\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\treturn collection.each( function( index ) {\n\t\t\tvar self = collection.eq( index );\n\t\t\tif ( valueIsFunction ) {\n\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t}\n\t\t\tdomManip( self, args, callback, ignored );\n\t\t} );\n\t}\n\n\tif ( l ) {\n\t\tfragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );\n\t\tfirst = fragment.firstChild;\n\n\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\tfragment = first;\n\t\t}\n\n\t\t// Require either new content or an interest in ignored elements to invoke the callback\n\t\tif ( first || ignored ) {\n\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\thasScripts = scripts.length;\n\n\t\t\t// Use the original fragment for the last item\n\t\t\t// instead of the first because it can end up\n\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tnode = fragment;\n\n\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\tif ( hasScripts ) {\n\n\t\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcallback.call( collection[ i ], node, i );\n\t\t\t}\n\n\t\t\tif ( hasScripts ) {\n\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t// Reenable scripts\n\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t!dataPriv.access( node, \"globalEval\" ) &&\n\t\t\t\t\t\tjQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\tif ( node.src && ( node.type || \"\" ).toLowerCase()  !== \"module\" ) {\n\n\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\tif ( jQuery._evalUrl && !node.noModule ) {\n\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src, {\n\t\t\t\t\t\t\t\t\tnonce: node.nonce || node.getAttribute( \"nonce\" )\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDOMEval( node.textContent.replace( rcleanScript, \"\" ), node, doc );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn collection;\n}\n\nfunction remove( elem, selector, keepData ) {\n\tvar node,\n\t\tnodes = selector ? jQuery.filter( selector, elem ) : elem,\n\t\ti = 0;\n\n\tfor ( ; ( node = nodes[ i ] ) != null; i++ ) {\n\t\tif ( !keepData && node.nodeType === 1 ) {\n\t\t\tjQuery.cleanData( getAll( node ) );\n\t\t}\n\n\t\tif ( node.parentNode ) {\n\t\t\tif ( keepData && isAttached( node ) ) {\n\t\t\t\tsetGlobalEval( getAll( node, \"script\" ) );\n\t\t\t}\n\t\t\tnode.parentNode.removeChild( node );\n\t\t}\n\t}\n\n\treturn elem;\n}\n\njQuery.extend( {\n\thtmlPrefilter: function( html ) {\n\t\treturn html.replace( rxhtmlTag, \"<$1></$2>\" );\n\t},\n\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = isAttached( elem );\n\n\t\t// Fix IE cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, type,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {\n\t\t\tif ( acceptData( elem ) ) {\n\t\t\t\tif ( ( data = elem[ dataPriv.expando ] ) ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataPriv.expando ] = undefined;\n\t\t\t\t}\n\t\t\t\tif ( elem[ dataUser.expando ] ) {\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataUser.expando ] = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n} );\n\njQuery.fn.extend( {\n\tdetach: function( selector ) {\n\t\treturn remove( this, selector, true );\n\t},\n\n\tremove: function( selector ) {\n\t\treturn remove( this, selector );\n\t},\n\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().each( function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t} );\n\t},\n\n\tprepend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t} );\n\t},\n\n\tbefore: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t} );\n\t},\n\n\tafter: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t} );\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = this[ i ] ) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t} );\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = jQuery.htmlPrefilter( value );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch ( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar ignored = [];\n\n\t\t// Make the changes, replacing each non-ignored context element with the new content\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tvar parent = this.parentNode;\n\n\t\t\tif ( jQuery.inArray( this, ignored ) < 0 ) {\n\t\t\t\tjQuery.cleanData( getAll( this ) );\n\t\t\t\tif ( parent ) {\n\t\t\t\t\tparent.replaceChild( elem, this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Force callback invocation\n\t\t}, ignored );\n\t}\n} );\n\njQuery.each( {\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t// .get() because push.apply(_, arraylike) throws on ancient WebKit\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n} );\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar getStyles = function( elem ) {\n\n\t\t// Support: IE <=11 only, Firefox <=30 (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tvar view = elem.ownerDocument.defaultView;\n\n\t\tif ( !view || !view.opener ) {\n\t\t\tview = window;\n\t\t}\n\n\t\treturn view.getComputedStyle( elem );\n\t};\n\nvar rboxStyle = new RegExp( cssExpand.join( \"|\" ), \"i\" );\n\n\n\n( function() {\n\n\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t// so they're executed at the same time to save the second computation.\n\tfunction computeStyleTests() {\n\n\t\t// This is a singleton, we need to execute it only once\n\t\tif ( !div ) {\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer.style.cssText = \"position:absolute;left:-11111px;width:60px;\" +\n\t\t\t\"margin-top:1px;padding:0;border:0\";\n\t\tdiv.style.cssText =\n\t\t\t\"position:relative;display:block;box-sizing:border-box;overflow:scroll;\" +\n\t\t\t\"margin:auto;border:1px;padding:1px;\" +\n\t\t\t\"width:60%;top:1%\";\n\t\tdocumentElement.appendChild( container ).appendChild( div );\n\n\t\tvar divStyle = window.getComputedStyle( div );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\n\t\t// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44\n\t\treliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;\n\n\t\t// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3\n\t\t// Some styles come back with percentage values, even though they shouldn't\n\t\tdiv.style.right = \"60%\";\n\t\tpixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;\n\n\t\t// Support: IE 9 - 11 only\n\t\t// Detect misreporting of content dimensions for box-sizing:border-box elements\n\t\tboxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;\n\n\t\t// Support: IE 9 only\n\t\t// Detect overflow:scroll screwiness (gh-3699)\n\t\t// Support: Chrome <=64\n\t\t// Don't get tricked when zoom affects offsetWidth (gh-4029)\n\t\tdiv.style.position = \"absolute\";\n\t\tscrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;\n\n\t\tdocumentElement.removeChild( container );\n\n\t\t// Nullify the div so it wouldn't be stored in the memory and\n\t\t// it will also be a sign that checks already performed\n\t\tdiv = null;\n\t}\n\n\tfunction roundPixelMeasures( measure ) {\n\t\treturn Math.round( parseFloat( measure ) );\n\t}\n\n\tvar pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,\n\t\treliableMarginLeftVal,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Finish early in limited (non-browser) environments\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE <=9 - 11 only\n\t// Style of cloned element affects source element cloned (#8908)\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tjQuery.extend( support, {\n\t\tboxSizingReliable: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\t\tpixelBoxStyles: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelBoxStylesVal;\n\t\t},\n\t\tpixelPosition: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelPositionVal;\n\t\t},\n\t\treliableMarginLeft: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn reliableMarginLeftVal;\n\t\t},\n\t\tscrollboxSize: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn scrollboxSizeVal;\n\t\t}\n\t} );\n} )();\n\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\n\t\t// Support: Firefox 51+\n\t\t// Retrieving style before computed somehow\n\t\t// fixes an issue with getting wrong values\n\t\t// on detached elements\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// getPropertyValue is needed for:\n\t//   .css('filter') (IE 9 only, #12537)\n\t//   .css('--customProperty) (#3144)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\n\t\tif ( ret === \"\" && !isAttached( elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// Android Browser returns percentage for some values,\n\t\t// but width seems to be reliably pixels.\n\t\t// This is against the CSSOM draft spec:\n\t\t// https://drafts.csswg.org/cssom/#resolved-values\n\t\tif ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret !== undefined ?\n\n\t\t// Support: IE <=9 - 11 only\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tif ( conditionFn() ) {\n\n\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t// to missing dependency), remove it.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\treturn ( this.get = hookFn ).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\nvar cssPrefixes = [ \"Webkit\", \"Moz\", \"ms\" ],\n\temptyStyle = document.createElement( \"div\" ).style,\n\tvendorProps = {};\n\n// Return a vendor-prefixed property or undefined\nfunction vendorPropName( name ) {\n\n\t// Check for vendor prefixed names\n\tvar capName = name[ 0 ].toUpperCase() + name.slice( 1 ),\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in emptyStyle ) {\n\t\t\treturn name;\n\t\t}\n\t}\n}\n\n// Return a potentially-mapped jQuery.cssProps or vendor prefixed property\nfunction finalPropName( name ) {\n\tvar final = jQuery.cssProps[ name ] || vendorProps[ name ];\n\n\tif ( final ) {\n\t\treturn final;\n\t}\n\tif ( name in emptyStyle ) {\n\t\treturn name;\n\t}\n\treturn vendorProps[ name ] = vendorPropName( name ) || name;\n}\n\n\nvar\n\n\t// Swappable if display is none or starts with table\n\t// except \"table\", \"table-cell\", or \"table-caption\"\n\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trcustomProp = /^--/,\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t};\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\n\t// Any relative (+/-) values have already been\n\t// normalized at this point\n\tvar matches = rcssNum.exec( value );\n\treturn matches ?\n\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {\n\tvar i = dimension === \"width\" ? 1 : 0,\n\t\textra = 0,\n\t\tdelta = 0;\n\n\t// Adjustment may not be necessary\n\tif ( box === ( isBorderBox ? \"border\" : \"content\" ) ) {\n\t\treturn 0;\n\t}\n\n\tfor ( ; i < 4; i += 2 ) {\n\n\t\t// Both box models exclude margin\n\t\tif ( box === \"margin\" ) {\n\t\t\tdelta += jQuery.css( elem, box + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\t// If we get here with a content-box, we're seeking \"padding\" or \"border\" or \"margin\"\n\t\tif ( !isBorderBox ) {\n\n\t\t\t// Add padding\n\t\t\tdelta += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// For \"border\" or \"margin\", add border\n\t\t\tif ( box !== \"padding\" ) {\n\t\t\t\tdelta += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\n\t\t\t// But still keep track of it otherwise\n\t\t\t} else {\n\t\t\t\textra += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\n\t\t// If we get here with a border-box (content + padding + border), we're seeking \"content\" or\n\t\t// \"padding\" or \"margin\"\n\t\t} else {\n\n\t\t\t// For \"content\", subtract padding\n\t\t\tif ( box === \"content\" ) {\n\t\t\t\tdelta -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// For \"content\" or \"padding\", subtract border\n\t\t\tif ( box !== \"margin\" ) {\n\t\t\t\tdelta -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Account for positive content-box scroll gutter when requested by providing computedVal\n\tif ( !isBorderBox && computedVal >= 0 ) {\n\n\t\t// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border\n\t\t// Assuming integer scroll gutter, subtract the rest and round down\n\t\tdelta += Math.max( 0, Math.ceil(\n\t\t\telem[ \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -\n\t\t\tcomputedVal -\n\t\t\tdelta -\n\t\t\textra -\n\t\t\t0.5\n\n\t\t// If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter\n\t\t// Use an explicit zero to avoid NaN (gh-3964)\n\t\t) ) || 0;\n\t}\n\n\treturn delta;\n}\n\nfunction getWidthOrHeight( elem, dimension, extra ) {\n\n\t// Start with computed style\n\tvar styles = getStyles( elem ),\n\n\t\t// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).\n\t\t// Fake content-box until we know it's needed to know the true value.\n\t\tboxSizingNeeded = !support.boxSizingReliable() || extra,\n\t\tisBorderBox = boxSizingNeeded &&\n\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\tvalueIsBorderBox = isBorderBox,\n\n\t\tval = curCSS( elem, dimension, styles ),\n\t\toffsetProp = \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );\n\n\t// Support: Firefox <=54\n\t// Return a confounding non-pixel value or feign ignorance, as appropriate.\n\tif ( rnumnonpx.test( val ) ) {\n\t\tif ( !extra ) {\n\t\t\treturn val;\n\t\t}\n\t\tval = \"auto\";\n\t}\n\n\n\t// Fall back to offsetWidth/offsetHeight when value is \"auto\"\n\t// This happens for inline elements with no explicit setting (gh-3571)\n\t// Support: Android <=4.1 - 4.3 only\n\t// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)\n\t// Support: IE 9-11 only\n\t// Also use offsetWidth/offsetHeight for when box sizing is unreliable\n\t// We use getClientRects() to check for hidden/disconnected.\n\t// In those cases, the computed value can be trusted to be border-box\n\tif ( ( !support.boxSizingReliable() && isBorderBox ||\n\t\tval === \"auto\" ||\n\t\t!parseFloat( val ) && jQuery.css( elem, \"display\", false, styles ) === \"inline\" ) &&\n\t\telem.getClientRects().length ) {\n\n\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t\t// Where available, offsetWidth/offsetHeight approximate border box dimensions.\n\t\t// Where not available (e.g., SVG), assume unreliable box-sizing and interpret the\n\t\t// retrieved value as a content box dimension.\n\t\tvalueIsBorderBox = offsetProp in elem;\n\t\tif ( valueIsBorderBox ) {\n\t\t\tval = elem[ offsetProp ];\n\t\t}\n\t}\n\n\t// Normalize \"\" and auto\n\tval = parseFloat( val ) || 0;\n\n\t// Adjust for the element's box model\n\treturn ( val +\n\t\tboxModelAdjustment(\n\t\t\telem,\n\t\t\tdimension,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles,\n\n\t\t\t// Provide the current computed size to request scroll gutter calculation (gh-3589)\n\t\t\tval\n\t\t)\n\t) + \"px\";\n}\n\njQuery.extend( {\n\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"animationIterationCount\": true,\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"gridArea\": true,\n\t\t\"gridColumn\": true,\n\t\t\"gridColumnEnd\": true,\n\t\t\"gridColumnStart\": true,\n\t\t\"gridRow\": true,\n\t\t\"gridRowEnd\": true,\n\t\t\"gridRowStart\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = camelCase( name ),\n\t\t\tisCustomProp = rcustomProp.test( name ),\n\t\t\tstyle = elem.style;\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to query the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\n\n\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\tif ( type === \"string\" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {\n\t\t\t\tvalue = adjustCSS( elem, name, ret );\n\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add the unit (except for certain CSS properties)\n\t\t\t// The isCustomProp check can be removed in jQuery 4.0 when we only auto-append\n\t\t\t// \"px\" to a few hardcoded values.\n\t\t\tif ( type === \"number\" && !isCustomProp ) {\n\t\t\t\tvalue += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? \"\" : \"px\" );\n\t\t\t}\n\n\t\t\t// background-* props affect original clone's values\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !( \"set\" in hooks ) ||\n\t\t\t\t( value = hooks.set( elem, value, extra ) ) !== undefined ) {\n\n\t\t\t\tif ( isCustomProp ) {\n\t\t\t\t\tstyle.setProperty( name, value );\n\t\t\t\t} else {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks &&\n\t\t\t\t( ret = hooks.get( elem, false, extra ) ) !== undefined ) {\n\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = camelCase( name ),\n\t\t\tisCustomProp = rcustomProp.test( name );\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to modify the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\n\n\t\t// Try prefixed name followed by the unprefixed name\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t// Convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || isFinite( num ) ? num || 0 : val;\n\t\t}\n\n\t\treturn val;\n\t}\n} );\n\njQuery.each( [ \"height\", \"width\" ], function( i, dimension ) {\n\tjQuery.cssHooks[ dimension ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) &&\n\n\t\t\t\t\t// Support: Safari 8+\n\t\t\t\t\t// Table columns in Safari have non-zero offsetWidth & zero\n\t\t\t\t\t// getBoundingClientRect().width unless display is changed.\n\t\t\t\t\t// Support: IE <=11 only\n\t\t\t\t\t// Running getBoundingClientRect on a disconnected node\n\t\t\t\t\t// in IE throws an error.\n\t\t\t\t\t( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?\n\t\t\t\t\t\tswap( elem, cssShow, function() {\n\t\t\t\t\t\t\treturn getWidthOrHeight( elem, dimension, extra );\n\t\t\t\t\t\t} ) :\n\t\t\t\t\t\tgetWidthOrHeight( elem, dimension, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar matches,\n\t\t\t\tstyles = getStyles( elem ),\n\n\t\t\t\t// Only read styles.position if the test has a chance to fail\n\t\t\t\t// to avoid forcing a reflow.\n\t\t\t\tscrollboxSizeBuggy = !support.scrollboxSize() &&\n\t\t\t\t\tstyles.position === \"absolute\",\n\n\t\t\t\t// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)\n\t\t\t\tboxSizingNeeded = scrollboxSizeBuggy || extra,\n\t\t\t\tisBorderBox = boxSizingNeeded &&\n\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\tsubtract = extra ?\n\t\t\t\t\tboxModelAdjustment(\n\t\t\t\t\t\telem,\n\t\t\t\t\t\tdimension,\n\t\t\t\t\t\textra,\n\t\t\t\t\t\tisBorderBox,\n\t\t\t\t\t\tstyles\n\t\t\t\t\t) :\n\t\t\t\t\t0;\n\n\t\t\t// Account for unreliable border-box dimensions by comparing offset* to computed and\n\t\t\t// faking a content-box to get border and padding (gh-3699)\n\t\t\tif ( isBorderBox && scrollboxSizeBuggy ) {\n\t\t\t\tsubtract -= Math.ceil(\n\t\t\t\t\telem[ \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -\n\t\t\t\t\tparseFloat( styles[ dimension ] ) -\n\t\t\t\t\tboxModelAdjustment( elem, dimension, \"border\", false, styles ) -\n\t\t\t\t\t0.5\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Convert to pixels if value adjustment is needed\n\t\t\tif ( subtract && ( matches = rcssNum.exec( value ) ) &&\n\t\t\t\t( matches[ 3 ] || \"px\" ) !== \"px\" ) {\n\n\t\t\t\telem.style[ dimension ] = value;\n\t\t\t\tvalue = jQuery.css( elem, dimension );\n\t\t\t}\n\n\t\t\treturn setPositiveNumber( elem, value, subtract );\n\t\t}\n\t};\n} );\n\njQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn ( parseFloat( curCSS( elem, \"marginLeft\" ) ) ||\n\t\t\t\telem.getBoundingClientRect().left -\n\t\t\t\t\tswap( elem, { marginLeft: 0 }, function() {\n\t\t\t\t\t\treturn elem.getBoundingClientRect().left;\n\t\t\t\t\t} )\n\t\t\t\t) + \"px\";\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each( {\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// Assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split( \" \" ) : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( prefix !== \"margin\" ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n} );\n\njQuery.fn.extend( {\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( Array.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t}\n} );\n\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || jQuery.easing._default;\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\t// Use a property on the element directly when it is not a DOM element,\n\t\t\t// or when there is no matching style property that exists.\n\t\t\tif ( tween.elem.nodeType !== 1 ||\n\t\t\t\ttween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// Passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails.\n\t\t\t// Simple values such as \"10px\" are parsed to Float;\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as-is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\n\t\t\t// Use step hook for back compat.\n\t\t\t// Use cssHook if its there.\n\t\t\t// Use .style if available and use plain properties where available.\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.nodeType === 1 && (\n\t\t\t\t\tjQuery.cssHooks[ tween.prop ] ||\n\t\t\t\t\ttween.elem.style[ finalPropName( tween.prop ) ] != null ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Support: IE <=9 only\n// Panic based approach to setting things on disconnected nodes\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t},\n\t_default: \"swing\"\n};\n\njQuery.fx = Tween.prototype.init;\n\n// Back compat <1.8 extension point\njQuery.fx.step = {};\n\n\n\n\nvar\n\tfxNow, inProgress,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trrun = /queueHooks$/;\n\nfunction schedule() {\n\tif ( inProgress ) {\n\t\tif ( document.hidden === false && window.requestAnimationFrame ) {\n\t\t\twindow.requestAnimationFrame( schedule );\n\t\t} else {\n\t\t\twindow.setTimeout( schedule, jQuery.fx.interval );\n\t\t}\n\n\t\tjQuery.fx.tick();\n\t}\n}\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\twindow.setTimeout( function() {\n\t\tfxNow = undefined;\n\t} );\n\treturn ( fxNow = Date.now() );\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\ti = 0,\n\t\tattrs = { height: type };\n\n\t// If we include width, step value is 1 to do all cssExpand values,\n\t// otherwise step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth ? 1 : 0;\n\tfor ( ; i < 4; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\nfunction createTween( value, prop, animation ) {\n\tvar tween,\n\t\tcollection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {\n\n\t\t\t// We're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\tvar prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,\n\t\tisBox = \"width\" in props || \"height\" in props,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHiddenWithinTree( elem ),\n\t\tdataShow = dataPriv.get( elem, \"fxshow\" );\n\n\t// Queue-skipping animations hijack the fx hooks\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always( function() {\n\n\t\t\t// Ensure the complete handler is called before this completes\n\t\t\tanim.always( function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t}\n\n\t// Detect show/hide animations\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.test( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// Pretend to be hidden if this is a \"show\" and\n\t\t\t\t// there is still data from a stopped show/hide\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\n\t\t\t\t// Ignore all other no-op show/hide data\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\t\t}\n\t}\n\n\t// Bail out if this is a no-op like .hide().hide()\n\tpropTween = !jQuery.isEmptyObject( props );\n\tif ( !propTween && jQuery.isEmptyObject( orig ) ) {\n\t\treturn;\n\t}\n\n\t// Restrict \"overflow\" and \"display\" styles during box animations\n\tif ( isBox && elem.nodeType === 1 ) {\n\n\t\t// Support: IE <=9 - 11, Edge 12 - 15\n\t\t// Record all 3 overflow attributes because IE does not infer the shorthand\n\t\t// from identically-valued overflowX and overflowY and Edge just mirrors\n\t\t// the overflowX value there.\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Identify a display type, preferring old show/hide data over the CSS cascade\n\t\trestoreDisplay = dataShow && dataShow.display;\n\t\tif ( restoreDisplay == null ) {\n\t\t\trestoreDisplay = dataPriv.get( elem, \"display\" );\n\t\t}\n\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\tif ( display === \"none\" ) {\n\t\t\tif ( restoreDisplay ) {\n\t\t\t\tdisplay = restoreDisplay;\n\t\t\t} else {\n\n\t\t\t\t// Get nonempty value(s) by temporarily forcing visibility\n\t\t\t\tshowHide( [ elem ], true );\n\t\t\t\trestoreDisplay = elem.style.display || restoreDisplay;\n\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\t\tshowHide( [ elem ] );\n\t\t\t}\n\t\t}\n\n\t\t// Animate inline elements as inline-block\n\t\tif ( display === \"inline\" || display === \"inline-block\" && restoreDisplay != null ) {\n\t\t\tif ( jQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t\t// Restore the original display value at the end of pure show/hide animations\n\t\t\t\tif ( !propTween ) {\n\t\t\t\t\tanim.done( function() {\n\t\t\t\t\t\tstyle.display = restoreDisplay;\n\t\t\t\t\t} );\n\t\t\t\t\tif ( restoreDisplay == null ) {\n\t\t\t\t\t\tdisplay = style.display;\n\t\t\t\t\t\trestoreDisplay = display === \"none\" ? \"\" : display;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tstyle.display = \"inline-block\";\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tanim.always( function() {\n\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t} );\n\t}\n\n\t// Implement show/hide animations\n\tpropTween = false;\n\tfor ( prop in orig ) {\n\n\t\t// General show/hide setup for this element animation\n\t\tif ( !propTween ) {\n\t\t\tif ( dataShow ) {\n\t\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\t\thidden = dataShow.hidden;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdataShow = dataPriv.access( elem, \"fxshow\", { display: restoreDisplay } );\n\t\t\t}\n\n\t\t\t// Store hidden/visible for toggle so `.stop().toggle()` \"reverses\"\n\t\t\tif ( toggle ) {\n\t\t\t\tdataShow.hidden = !hidden;\n\t\t\t}\n\n\t\t\t// Show elements before animating them\n\t\t\tif ( hidden ) {\n\t\t\t\tshowHide( [ elem ], true );\n\t\t\t}\n\n\t\t\t/* eslint-disable no-loop-func */\n\n\t\t\tanim.done( function() {\n\n\t\t\t/* eslint-enable no-loop-func */\n\n\t\t\t\t// The final step of a \"hide\" animation is actually hiding the element\n\t\t\t\tif ( !hidden ) {\n\t\t\t\t\tshowHide( [ elem ] );\n\t\t\t\t}\n\t\t\t\tdataPriv.remove( elem, \"fxshow\" );\n\t\t\t\tfor ( prop in orig ) {\n\t\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\t// Per-property setup\n\t\tpropTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\t\tif ( !( prop in dataShow ) ) {\n\t\t\tdataShow[ prop ] = propTween.start;\n\t\t\tif ( hidden ) {\n\t\t\t\tpropTween.end = propTween.start;\n\t\t\t\tpropTween.start = 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( Array.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// Not quite $.extend, this won't overwrite existing keys.\n\t\t\t// Reusing 'index' because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = Animation.prefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\n\t\t\t// Don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t} ),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\n\t\t\t\t// Support: Android 2.3 only\n\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ] );\n\n\t\t\t// If there's more to do, yield\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t}\n\n\t\t\t// If this was an empty animation, synthesize a final progress notification\n\t\t\tif ( !length ) {\n\t\t\t\tdeferred.notifyWith( elem, [ animation, 1, 0 ] );\n\t\t\t}\n\n\t\t\t// Resolve the animation and report its conclusion\n\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\treturn false;\n\t\t},\n\t\tanimation = deferred.promise( {\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, {\n\t\t\t\tspecialEasing: {},\n\t\t\t\teasing: jQuery.easing._default\n\t\t\t}, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\n\t\t\t\t\t// If we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// Resolve when we played the last frame; otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.notifyWith( elem, [ animation, 1, 0 ] );\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t} ),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length; index++ ) {\n\t\tresult = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\tif ( isFunction( result.stop ) ) {\n\t\t\t\tjQuery._queueHooks( animation.elem, animation.opts.queue ).stop =\n\t\t\t\t\tresult.stop.bind( result );\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\t// Attach callbacks from options\n\tanimation\n\t\t.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t} )\n\t);\n\n\treturn animation;\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweeners: {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value );\n\t\t\tadjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );\n\t\t\treturn tween;\n\t\t} ]\n\t},\n\n\ttweener: function( props, callback ) {\n\t\tif ( isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.match( rnothtmlwhite );\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\tAnimation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];\n\t\t\tAnimation.tweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilters: [ defaultPrefilter ],\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tAnimation.prefilters.unshift( callback );\n\t\t} else {\n\t\t\tAnimation.prefilters.push( callback );\n\t\t}\n\t}\n} );\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tisFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !isFunction( easing ) && easing\n\t};\n\n\t// Go to the end state if fx are off\n\tif ( jQuery.fx.off ) {\n\t\topt.duration = 0;\n\n\t} else {\n\t\tif ( typeof opt.duration !== \"number\" ) {\n\t\t\tif ( opt.duration in jQuery.fx.speeds ) {\n\t\t\t\topt.duration = jQuery.fx.speeds[ opt.duration ];\n\n\t\t\t} else {\n\t\t\t\topt.duration = jQuery.fx.speeds._default;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.fn.extend( {\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// Show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHiddenWithinTree ).css( \"opacity\", 0 ).show()\n\n\t\t\t// Animate to the value specified\n\t\t\t.end().animate( { opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || dataPriv.get( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = dataPriv.get( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this &&\n\t\t\t\t\t( type == null || timers[ index ].queue === type ) ) {\n\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Start the next in the queue if the last step wasn't forced.\n\t\t\t// Timers currently will call their complete callbacks, which\n\t\t\t// will dequeue but only if they were gotoEnd.\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t} );\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tvar index,\n\t\t\t\tdata = dataPriv.get( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// Enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// Empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// Look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t} );\n\t}\n} );\n\njQuery.each( [ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n} );\n\n// Generate shortcuts for custom animations\njQuery.each( {\n\tslideDown: genFx( \"show\" ),\n\tslideUp: genFx( \"hide\" ),\n\tslideToggle: genFx( \"toggle\" ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n} );\n\njQuery.timers = [];\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ti = 0,\n\t\ttimers = jQuery.timers;\n\n\tfxNow = Date.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\n\t\t// Run the timer and safely remove it when done (allowing for external removal)\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tjQuery.timers.push( timer );\n\tjQuery.fx.start();\n};\n\njQuery.fx.interval = 13;\njQuery.fx.start = function() {\n\tif ( inProgress ) {\n\t\treturn;\n\t}\n\n\tinProgress = true;\n\tschedule();\n};\n\njQuery.fx.stop = function() {\n\tinProgress = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = window.setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\twindow.clearTimeout( timeout );\n\t\t};\n\t} );\n};\n\n\n( function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\tinput.type = \"checkbox\";\n\n\t// Support: Android <=4.3 only\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE <=11 only\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: IE <=11 only\n\t// An input loses its value after becoming a radio\n\tinput = document.createElement( \"input\" );\n\tinput.value = \"t\";\n\tinput.type = \"radio\";\n\tsupport.radioValue = input.value === \"t\";\n} )();\n\n\nvar boolHook,\n\tattrHandle = jQuery.expr.attrHandle;\n\njQuery.fn.extend( {\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tattr: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set attributes on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// Attribute hooks are determined by the lowercase version\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\thooks = jQuery.attrHooks[ name.toLowerCase() ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\treturn value;\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tret = jQuery.find.attr( elem, name );\n\n\t\t// Non-existent attributes return null, we normalize to undefined\n\t\treturn ret == null ? undefined : ret;\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\tnodeName( elem, \"input\" ) ) {\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name,\n\t\t\ti = 0,\n\n\t\t\t// Attribute names can contain non-HTML whitespace characters\n\t\t\t// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n\t\t\tattrNames = value && value.match( rnothtmlwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( ( name = attrNames[ i++ ] ) ) {\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\n\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar ret, handle,\n\t\t\tlowercaseName = name.toLowerCase();\n\n\t\tif ( !isXML ) {\n\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ lowercaseName ];\n\t\t\tattrHandle[ lowercaseName ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tlowercaseName :\n\t\t\t\tnull;\n\t\t\tattrHandle[ lowercaseName ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n} );\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button)$/i,\n\trclickable = /^(?:a|area)$/i;\n\njQuery.fn.extend( {\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\treturn ( elem[ name ] = value );\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\treturn elem[ name ];\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\t// Support: IE <=9 - 11 only\n\t\t\t\t// elem.tabIndex doesn't always return the\n\t\t\t\t// correct value when it hasn't been explicitly set\n\t\t\t\t// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\tif ( tabindex ) {\n\t\t\t\t\treturn parseInt( tabindex, 10 );\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\trfocusable.test( elem.nodeName ) ||\n\t\t\t\t\trclickable.test( elem.nodeName ) &&\n\t\t\t\t\telem.href\n\t\t\t\t) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t}\n} );\n\n// Support: IE <=11 only\n// Accessing the selectedIndex property\n// forces the browser to respect setting selected\n// on the option\n// The getter ensures a default option is selected\n// when in an optgroup\n// eslint rule \"no-unused-expressions\" is disabled for this code\n// since it considers such accessions noop\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tset: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\njQuery.each( [\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n} );\n\n\n\n\n\t// Strip and collapse whitespace according to HTML spec\n\t// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace\n\tfunction stripAndCollapse( value ) {\n\t\tvar tokens = value.match( rnothtmlwhite ) || [];\n\t\treturn tokens.join( \" \" );\n\t}\n\n\nfunction getClass( elem ) {\n\treturn elem.getAttribute && elem.getAttribute( \"class\" ) || \"\";\n}\n\nfunction classesToArray( value ) {\n\tif ( Array.isArray( value ) ) {\n\t\treturn value;\n\t}\n\tif ( typeof value === \"string\" ) {\n\t\treturn value.match( rnothtmlwhite ) || [];\n\t}\n\treturn [];\n}\n\njQuery.fn.extend( {\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tclasses = classesToArray( value );\n\n\t\tif ( classes.length ) {\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( !arguments.length ) {\n\t\t\treturn this.attr( \"class\", \"\" );\n\t\t}\n\n\t\tclasses = classesToArray( value );\n\n\t\tif ( classes.length ) {\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) > -1 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisValidValue = type === \"string\" || Array.isArray( value );\n\n\t\tif ( typeof stateVal === \"boolean\" && isValidValue ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).toggleClass(\n\t\t\t\t\tvalue.call( this, i, getClass( this ), stateVal ),\n\t\t\t\t\tstateVal\n\t\t\t\t);\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar className, i, self, classNames;\n\n\t\t\tif ( isValidValue ) {\n\n\t\t\t\t// Toggle individual class names\n\t\t\t\ti = 0;\n\t\t\t\tself = jQuery( this );\n\t\t\t\tclassNames = classesToArray( value );\n\n\t\t\t\twhile ( ( className = classNames[ i++ ] ) ) {\n\n\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( value === undefined || type === \"boolean\" ) {\n\t\t\t\tclassName = getClass( this );\n\t\t\t\tif ( className ) {\n\n\t\t\t\t\t// Store className if set\n\t\t\t\t\tdataPriv.set( this, \"__className__\", className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tif ( this.setAttribute ) {\n\t\t\t\t\tthis.setAttribute( \"class\",\n\t\t\t\t\t\tclassName || value === false ?\n\t\t\t\t\t\t\"\" :\n\t\t\t\t\t\tdataPriv.get( this, \"__className__\" ) || \"\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className, elem,\n\t\t\ti = 0;\n\n\t\tclassName = \" \" + selector + \" \";\n\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\tif ( elem.nodeType === 1 &&\n\t\t\t\t( \" \" + stripAndCollapse( getClass( elem ) ) + \" \" ).indexOf( className ) > -1 ) {\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n} );\n\n\n\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend( {\n\tval: function( value ) {\n\t\tvar hooks, ret, valueIsFunction,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] ||\n\t\t\t\t\tjQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks &&\n\t\t\t\t\t\"get\" in hooks &&\n\t\t\t\t\t( ret = hooks.get( elem, \"value\" ) ) !== undefined\n\t\t\t\t) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\t// Handle most common string cases\n\t\t\t\tif ( typeof ret === \"string\" ) {\n\t\t\t\t\treturn ret.replace( rreturn, \"\" );\n\t\t\t\t}\n\n\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\treturn ret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tvalueIsFunction = isFunction( value );\n\n\t\treturn this.each( function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( valueIsFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\n\t\t\t} else if ( Array.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !( \"set\" in hooks ) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\n\t\t\t\t\t// Support: IE <=10 - 11 only\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\t// Strip and collapse whitespace\n\t\t\t\t\t// https://html.spec.whatwg.org/#strip-and-collapse-whitespace\n\t\t\t\t\tstripAndCollapse( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option, i,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\",\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length;\n\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\ti = max;\n\n\t\t\t\t} else {\n\t\t\t\t\ti = one ? index : 0;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t// IE8-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t!option.disabled &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled ||\n\t\t\t\t\t\t\t\t!nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t/* eslint-disable no-cond-assign */\n\n\t\t\t\t\tif ( option.selected =\n\t\t\t\t\t\tjQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1\n\t\t\t\t\t) {\n\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* eslint-enable no-cond-assign */\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Radios and checkboxes getter/setter\njQuery.each( [ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( Array.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\treturn elem.getAttribute( \"value\" ) === null ? \"on\" : elem.value;\n\t\t};\n\t}\n} );\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\nsupport.focusin = \"onfocusin\" in window;\n\n\nvar rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\tstopPropagationCallback = function( e ) {\n\t\te.stopPropagation();\n\t};\n\njQuery.extend( jQuery.event, {\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special, lastElement,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split( \".\" ) : [];\n\n\t\tcur = lastElement = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) > -1 ) {\n\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split( \".\" );\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf( \":\" ) < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.rnamespace = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === ( elem.ownerDocument || document ) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tlastElement = cur;\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( dataPriv.get( cur, \"events\" ) || {} )[ event.type ] &&\n\t\t\t\tdataPriv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( ( !special._default ||\n\t\t\t\tspecial._default.apply( eventPath.pop(), data ) === false ) &&\n\t\t\t\tacceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name as the event.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\n\t\t\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\t\t\tlastElement.addEventListener( type, stopPropagationCallback );\n\t\t\t\t\t}\n\n\t\t\t\t\telem[ type ]();\n\n\t\t\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\t\t\tlastElement.removeEventListener( type, stopPropagationCallback );\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Piggyback on a donor event to simulate a different one\n\t// Used only for `focus(in | out)` events\n\tsimulate: function( type, elem, event ) {\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true\n\t\t\t}\n\t\t);\n\n\t\tjQuery.event.trigger( e, null, elem );\n\t}\n\n} );\n\njQuery.fn.extend( {\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t} );\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[ 0 ];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n} );\n\n\n// Support: Firefox <=44\n// Firefox doesn't have focus(in | out) events\n// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787\n//\n// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1\n// focus(in | out) events fire after focus & blur events,\n// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order\n// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857\nif ( !support.focusin ) {\n\tjQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );\n\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tdataPriv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tdataPriv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdataPriv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t} );\n}\nvar location = window.location;\n\nvar nonce = Date.now();\n\nvar rquery = ( /\\?/ );\n\n\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\n\t// Support: IE 9 - 11 only\n\t// IE throws on parseFromString with invalid input.\n\ttry {\n\t\txml = ( new window.DOMParser() ).parseFromString( data, \"text/xml\" );\n\t} catch ( e ) {\n\t\txml = undefined;\n\t}\n\n\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( Array.isArray( obj ) ) {\n\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams(\n\t\t\t\t\tprefix + \"[\" + ( typeof v === \"object\" && v != null ? i : \"\" ) + \"]\",\n\t\t\t\t\tv,\n\t\t\t\t\ttraditional,\n\t\t\t\t\tadd\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\n\t} else if ( !traditional && toType( obj ) === \"object\" ) {\n\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, valueOrFunction ) {\n\n\t\t\t// If value is a function, invoke it and use its return value\n\t\t\tvar value = isFunction( valueOrFunction ) ?\n\t\t\t\tvalueOrFunction() :\n\t\t\t\tvalueOrFunction;\n\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( value == null ? \"\" : value );\n\t\t};\n\n\tif ( a == null ) {\n\t\treturn \"\";\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t} );\n\n\t} else {\n\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" );\n};\n\njQuery.fn.extend( {\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map( function() {\n\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t} )\n\t\t.filter( function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t} )\n\t\t.map( function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\tif ( val == null ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif ( Array.isArray( val ) ) {\n\t\t\t\treturn jQuery.map( val, function( val ) {\n\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t} ).get();\n\t}\n} );\n\n\nvar\n\tr20 = /%20/g,\n\trhash = /#.*$/,\n\trantiCache = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat( \"*\" ),\n\n\t// Anchor tag for parsing the document origin\n\toriginAnchor = document.createElement( \"a\" );\n\toriginAnchor.href = location.href;\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];\n\n\t\tif ( isFunction( func ) ) {\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( ( dataType = dataTypes[ i++ ] ) ) {\n\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[ 0 ] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif ( typeof dataTypeOrTransport === \"string\" &&\n\t\t\t\t!seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t} );\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\n/* Handles responses to an ajax request:\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar ct, type, finalDataType, firstDataType,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"Content-Type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[ 0 ] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s.throws ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tstate: \"parsererror\",\n\t\t\t\t\t\t\t\terror: conv ? e : \"No conversion from \" + prev + \" to \" + current\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n\njQuery.extend( {\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: location.href,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( location.protocol ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /\\bxml\\b/,\n\t\t\thtml: /\\bhtml/,\n\t\t\tjson: /\\bjson\\b/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\",\n\t\t\tjson: \"responseJSON\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": JSON.parse,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar transport,\n\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\n\t\t\t// Url cleanup var\n\t\t\turlAnchor,\n\n\t\t\t// Request state (becomes false upon send and true upon completion)\n\t\t\tcompleted,\n\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\n\t\t\t// Loop variable\n\t\t\ti,\n\n\t\t\t// uncached part of the url\n\t\t\tuncached,\n\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context &&\n\t\t\t\t( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\t\tjQuery.event,\n\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( completed ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[ 1 ].toLowerCase() + \" \" ] =\n\t\t\t\t\t\t\t\t\t( responseHeaders[ match[ 1 ].toLowerCase() + \" \" ] || [] )\n\t\t\t\t\t\t\t\t\t\t.concat( match[ 2 ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() + \" \" ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match.join( \", \" );\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn completed ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\tname = requestHeadersNames[ name.toLowerCase() ] =\n\t\t\t\t\t\t\trequestHeadersNames[ name.toLowerCase() ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( completed ) {\n\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Lazy-add the new callbacks in a way that preserves old ones\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\n\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || location.href ) + \"\" )\n\t\t\t.replace( rprotocol, location.protocol + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = ( s.dataType || \"*\" ).toLowerCase().match( rnothtmlwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when the origin doesn't match the current origin.\n\t\tif ( s.crossDomain == null ) {\n\t\t\turlAnchor = document.createElement( \"a\" );\n\n\t\t\t// Support: IE <=8 - 11, Edge 12 - 15\n\t\t\t// IE throws exception on accessing the href property if url is malformed,\n\t\t\t// e.g. http://example.com:80x/\n\t\t\ttry {\n\t\t\t\turlAnchor.href = s.url;\n\n\t\t\t\t// Support: IE <=8 - 11 only\n\t\t\t\t// Anchor's host property isn't correctly set when s.url is relative\n\t\t\t\turlAnchor.href = urlAnchor.href;\n\t\t\t\ts.crossDomain = originAnchor.protocol + \"//\" + originAnchor.host !==\n\t\t\t\t\turlAnchor.protocol + \"//\" + urlAnchor.host;\n\t\t\t} catch ( e ) {\n\n\t\t\t\t// If there is an error parsing the URL, assume it is crossDomain,\n\t\t\t\t// it can be rejected by the transport if it is invalid\n\t\t\t\ts.crossDomain = true;\n\t\t\t}\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( completed ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\t// Remove hash to simplify url manipulation\n\t\tcacheURL = s.url.replace( rhash, \"\" );\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// Remember the hash so we can put it back\n\t\t\tuncached = s.url.slice( cacheURL.length );\n\n\t\t\t// If data is available and should be processed, append data to url\n\t\t\tif ( s.data && ( s.processData || typeof s.data === \"string\" ) ) {\n\t\t\t\tcacheURL += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data;\n\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add or update anti-cache param if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\tcacheURL = cacheURL.replace( rantiCache, \"$1\" );\n\t\t\t\tuncached = ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + ( nonce++ ) + uncached;\n\t\t\t}\n\n\t\t\t// Put hash and anti-cache on the URL that will be requested (gh-1732)\n\t\t\ts.url = cacheURL + uncached;\n\n\t\t// Change '%20' to '+' if this is encoded form body content (gh-2658)\n\t\t} else if ( s.data && s.processData &&\n\t\t\t( s.contentType || \"\" ).indexOf( \"application/x-www-form-urlencoded\" ) === 0 ) {\n\t\t\ts.data = s.data.replace( r20, \"+\" );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[ 0 ] ] +\n\t\t\t\t\t( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend &&\n\t\t\t( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {\n\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// Aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tcompleteDeferred.add( s.complete );\n\t\tjqXHR.done( s.success );\n\t\tjqXHR.fail( s.error );\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\n\t\t\t// If request was aborted inside ajaxSend, stop there\n\t\t\tif ( completed ) {\n\t\t\t\treturn jqXHR;\n\t\t\t}\n\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = window.setTimeout( function() {\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tcompleted = false;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\n\t\t\t\t// Rethrow post-completion exceptions\n\t\t\t\tif ( completed ) {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\n\t\t\t\t// Propagate others as results\n\t\t\t\tdone( -1, e );\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Ignore repeat invocations\n\t\t\tif ( completed ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcompleted = true;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\twindow.clearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Determine if successful\n\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( isSuccess ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"Last-Modified\" );\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"etag\" );\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\terror = response.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Extract error from statusText and normalize for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t}\n} );\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\n\t\t// Shift arguments if data argument was omitted\n\t\tif ( isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\t// The url can be an options object (which then must have .url)\n\t\treturn jQuery.ajax( jQuery.extend( {\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t}, jQuery.isPlainObject( url ) && url ) );\n\t};\n} );\n\n\njQuery._evalUrl = function( url, options ) {\n\treturn jQuery.ajax( {\n\t\turl: url,\n\n\t\t// Make this explicit, since user can override this through ajaxSetup (#11264)\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tcache: true,\n\t\tasync: false,\n\t\tglobal: false,\n\n\t\t// Only evaluate the response if it is successful (gh-4126)\n\t\t// dataFilter is not invoked for failure responses, so using it instead\n\t\t// of the default converter is kludgy but it works.\n\t\tconverters: {\n\t\t\t\"text script\": function() {}\n\t\t},\n\t\tdataFilter: function( response ) {\n\t\t\tjQuery.globalEval( response, options );\n\t\t}\n\t} );\n};\n\n\njQuery.fn.extend( {\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( this[ 0 ] ) {\n\t\t\tif ( isFunction( html ) ) {\n\t\t\t\thtml = html.call( this[ 0 ] );\n\t\t\t}\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map( function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t} ).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( isFunction( html ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call( this, i ) );\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t} );\n\t},\n\n\twrap: function( html ) {\n\t\tvar htmlIsFunction = isFunction( html );\n\n\t\treturn this.each( function( i ) {\n\t\t\tjQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );\n\t\t} );\n\t},\n\n\tunwrap: function( selector ) {\n\t\tthis.parent( selector ).not( \"body\" ).each( function() {\n\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t} );\n\t\treturn this;\n\t}\n} );\n\n\njQuery.expr.pseudos.hidden = function( elem ) {\n\treturn !jQuery.expr.pseudos.visible( elem );\n};\njQuery.expr.pseudos.visible = function( elem ) {\n\treturn !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );\n};\n\n\n\n\njQuery.ajaxSettings.xhr = function() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch ( e ) {}\n};\n\nvar xhrSuccessStatus = {\n\n\t\t// File protocol always yields status code 0, assume 200\n\t\t0: 200,\n\n\t\t// Support: IE <=9 only\n\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t1223: 204\n\t},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nsupport.ajax = xhrSupported = !!xhrSupported;\n\njQuery.ajaxTransport( function( options ) {\n\tvar callback, errorCallback;\n\n\t// Cross domain only allowed if supported through XMLHttpRequest\n\tif ( support.cors || xhrSupported && !options.crossDomain ) {\n\t\treturn {\n\t\t\tsend: function( headers, complete ) {\n\t\t\t\tvar i,\n\t\t\t\t\txhr = options.xhr();\n\n\t\t\t\txhr.open(\n\t\t\t\t\toptions.type,\n\t\t\t\t\toptions.url,\n\t\t\t\t\toptions.async,\n\t\t\t\t\toptions.username,\n\t\t\t\t\toptions.password\n\t\t\t\t);\n\n\t\t\t\t// Apply custom fields if provided\n\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Override mime type if needed\n\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t}\n\n\t\t\t\t// X-Requested-With header\n\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\tif ( !options.crossDomain && !headers[ \"X-Requested-With\" ] ) {\n\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t}\n\n\t\t\t\t// Set headers\n\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t}\n\n\t\t\t\t// Callback\n\t\t\t\tcallback = function( type ) {\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tcallback = errorCallback = xhr.onload =\n\t\t\t\t\t\t\t\txhr.onerror = xhr.onabort = xhr.ontimeout =\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\n\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t// On a manual native abort, IE9 throws\n\t\t\t\t\t\t\t\t// errors on any property access that is not readyState\n\t\t\t\t\t\t\t\tif ( typeof xhr.status !== \"number\" ) {\n\t\t\t\t\t\t\t\t\tcomplete( 0, \"error\" );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcomplete(\n\n\t\t\t\t\t\t\t\t\t\t// File: protocol always yields status 0; see #8605, #14207\n\t\t\t\t\t\t\t\t\t\txhr.status,\n\t\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText,\n\n\t\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t\t// IE9 has no XHR2 but throws on binary (trac-11426)\n\t\t\t\t\t\t\t\t\t// For XHR2 non-text, let the caller handle it (gh-2498)\n\t\t\t\t\t\t\t\t\t( xhr.responseType || \"text\" ) !== \"text\"  ||\n\t\t\t\t\t\t\t\t\ttypeof xhr.responseText !== \"string\" ?\n\t\t\t\t\t\t\t\t\t\t{ binary: xhr.response } :\n\t\t\t\t\t\t\t\t\t\t{ text: xhr.responseText },\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\t// Listen to events\n\t\t\t\txhr.onload = callback();\n\t\t\t\terrorCallback = xhr.onerror = xhr.ontimeout = callback( \"error\" );\n\n\t\t\t\t// Support: IE 9 only\n\t\t\t\t// Use onreadystatechange to replace onabort\n\t\t\t\t// to handle uncaught aborts\n\t\t\t\tif ( xhr.onabort !== undefined ) {\n\t\t\t\t\txhr.onabort = errorCallback;\n\t\t\t\t} else {\n\t\t\t\t\txhr.onreadystatechange = function() {\n\n\t\t\t\t\t\t// Check readyState before timeout as it changes\n\t\t\t\t\t\tif ( xhr.readyState === 4 ) {\n\n\t\t\t\t\t\t\t// Allow onerror to be called first,\n\t\t\t\t\t\t\t// but that will not handle a native abort\n\t\t\t\t\t\t\t// Also, save errorCallback to a variable\n\t\t\t\t\t\t\t// as xhr.onerror cannot be accessed\n\t\t\t\t\t\t\twindow.setTimeout( function() {\n\t\t\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\t\t\terrorCallback();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Create the abort callback\n\t\t\t\tcallback = callback( \"abort\" );\n\n\t\t\t\ttry {\n\n\t\t\t\t\t// Do send the request (this may raise an exception)\n\t\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// #14683: Only rethrow if this hasn't been notified as an error yet\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n} );\n\n\n\n\n// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)\njQuery.ajaxPrefilter( function( s ) {\n\tif ( s.crossDomain ) {\n\t\ts.contents.script = false;\n\t}\n} );\n\n// Install script dataType\njQuery.ajaxSetup( {\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, \" +\n\t\t\t\"application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /\\b(?:java|ecma)script\\b/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n} );\n\n// Handle cache's special case and crossDomain\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t}\n} );\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\n\t// This transport only deals with cross domain or forced-by-attrs requests\n\tif ( s.crossDomain || s.scriptAttrs ) {\n\t\tvar script, callback;\n\t\treturn {\n\t\t\tsend: function( _, complete ) {\n\t\t\t\tscript = jQuery( \"<script>\" )\n\t\t\t\t\t.attr( s.scriptAttrs || {} )\n\t\t\t\t\t.prop( { charset: s.scriptCharset, src: s.url } )\n\t\t\t\t\t.on( \"load error\", callback = function( evt ) {\n\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n} );\n\n\n\n\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup( {\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n} );\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" &&\n\t\t\t\t( s.contentType || \"\" )\n\t\t\t\t\t.indexOf( \"application/x-www-form-urlencoded\" ) === 0 &&\n\t\t\t\trjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[ \"script json\" ] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// Force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always( function() {\n\n\t\t\t// If previous value didn't exist - remove it\n\t\t\tif ( overwritten === undefined ) {\n\t\t\t\tjQuery( window ).removeProp( callbackName );\n\n\t\t\t// Otherwise restore preexisting value\n\t\t\t} else {\n\t\t\t\twindow[ callbackName ] = overwritten;\n\t\t\t}\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\n\t\t\t\t// Make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// Save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t} );\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n} );\n\n\n\n\n// Support: Safari 8 only\n// In Safari 8 documents created via document.implementation.createHTMLDocument\n// collapse sibling forms: the second one becomes a child of the first one.\n// Because of that, this security measure has to be disabled in Safari 8.\n// https://bugs.webkit.org/show_bug.cgi?id=137337\nsupport.createHTMLDocument = ( function() {\n\tvar body = document.implementation.createHTMLDocument( \"\" ).body;\n\tbody.innerHTML = \"<form></form><form></form>\";\n\treturn body.childNodes.length === 2;\n} )();\n\n\n// Argument \"data\" should be string of html\n// context (optional): If specified, the fragment will be created in this context,\n// defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( typeof data !== \"string\" ) {\n\t\treturn [];\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\n\tvar base, parsed, scripts;\n\n\tif ( !context ) {\n\n\t\t// Stop scripts or inline event handlers from being executed immediately\n\t\t// by using document.implementation\n\t\tif ( support.createHTMLDocument ) {\n\t\t\tcontext = document.implementation.createHTMLDocument( \"\" );\n\n\t\t\t// Set the base href for the created document\n\t\t\t// so any parsed elements with URLs\n\t\t\t// are based on the document's URL (gh-2965)\n\t\t\tbase = context.createElement( \"base\" );\n\t\t\tbase.href = document.location.href;\n\t\t\tcontext.head.appendChild( base );\n\t\t} else {\n\t\t\tcontext = document;\n\t\t}\n\t}\n\n\tparsed = rsingleTag.exec( data );\n\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[ 1 ] ) ];\n\t}\n\n\tparsed = buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf( \" \" );\n\n\tif ( off > -1 ) {\n\t\tselector = stripAndCollapse( url.slice( off ) );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax( {\n\t\t\turl: url,\n\n\t\t\t// If \"type\" variable is undefined, then \"GET\" method will be used.\n\t\t\t// Make value of this field explicit since\n\t\t\t// user can override it through ajaxSetup method\n\t\t\ttype: type || \"GET\",\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t} ).done( function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery( \"<div>\" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t// If the request succeeds, this function gets \"data\", \"status\", \"jqXHR\"\n\t\t// but they are ignored because response was set above.\n\t\t// If it fails, this function gets \"jqXHR\", \"status\", \"error\"\n\t\t} ).always( callback && function( jqXHR, status ) {\n\t\t\tself.each( function() {\n\t\t\t\tcallback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t\t} );\n\t\t} );\n\t}\n\n\treturn this;\n};\n\n\n\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [\n\t\"ajaxStart\",\n\t\"ajaxStop\",\n\t\"ajaxComplete\",\n\t\"ajaxError\",\n\t\"ajaxSuccess\",\n\t\"ajaxSend\"\n], function( i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n} );\n\n\n\n\njQuery.expr.pseudos.animated = function( elem ) {\n\treturn jQuery.grep( jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t} ).length;\n};\n\n\n\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// Set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\t( curCSSTop + curCSSLeft ).indexOf( \"auto\" ) > -1;\n\n\t\t// Need to be able to calculate position if either\n\t\t// top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( isFunction( options ) ) {\n\n\t\t\t// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)\n\t\t\toptions = options.call( elem, i, jQuery.extend( {}, curOffset ) );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend( {\n\n\t// offset() relates an element's border box to the document origin\n\toffset: function( options ) {\n\n\t\t// Preserve chaining for setter\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each( function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t} );\n\t\t}\n\n\t\tvar rect, win,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !elem ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Return zeros for disconnected and hidden (display: none) elements (gh-2310)\n\t\t// Support: IE <=11 only\n\t\t// Running getBoundingClientRect on a\n\t\t// disconnected node in IE throws an error\n\t\tif ( !elem.getClientRects().length ) {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t\t// Get document-relative position by adding viewport scroll to viewport-relative gBCR\n\t\trect = elem.getBoundingClientRect();\n\t\twin = elem.ownerDocument.defaultView;\n\t\treturn {\n\t\t\ttop: rect.top + win.pageYOffset,\n\t\t\tleft: rect.left + win.pageXOffset\n\t\t};\n\t},\n\n\t// position() relates an element's margin box to its offset parent's padding box\n\t// This corresponds to the behavior of CSS absolute positioning\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset, doc,\n\t\t\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// position:fixed elements are offset from the viewport, which itself always has zero offset\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\n\t\t\t// Assume position:fixed implies availability of getBoundingClientRect\n\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t} else {\n\t\t\toffset = this.offset();\n\n\t\t\t// Account for the *real* offset parent, which can be the document or its root element\n\t\t\t// when a statically positioned element is identified\n\t\t\tdoc = elem.ownerDocument;\n\t\t\toffsetParent = elem.offsetParent || doc.documentElement;\n\t\t\twhile ( offsetParent &&\n\t\t\t\t( offsetParent === doc.body || offsetParent === doc.documentElement ) &&\n\t\t\t\tjQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\n\t\t\t\toffsetParent = offsetParent.parentNode;\n\t\t\t}\n\t\t\tif ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {\n\n\t\t\t\t// Incorporate borders into its offset, since they are outside its content origin\n\t\t\t\tparentOffset = jQuery( offsetParent ).offset();\n\t\t\t\tparentOffset.top += jQuery.css( offsetParent, \"borderTopWidth\", true );\n\t\t\t\tparentOffset.left += jQuery.css( offsetParent, \"borderLeftWidth\", true );\n\t\t\t}\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\t// This method will return documentElement in the following cases:\n\t// 1) For the element inside the iframe without offsetParent, this method will return\n\t//    documentElement of the parent window\n\t// 2) For the hidden or detached element\n\t// 3) For body or html element, i.e. in case of the html node - it will return itself\n\t//\n\t// but those exceptions were never presented as a real life use-cases\n\t// and might be considered as more preferable results.\n\t//\n\t// This logic, however, is not guaranteed and can change at any point in the future\n\toffsetParent: function() {\n\t\treturn this.map( function() {\n\t\t\tvar offsetParent = this.offsetParent;\n\n\t\t\twhile ( offsetParent && jQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || documentElement;\n\t\t} );\n\t}\n} );\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\n\t\t\t// Coalesce documents and windows\n\t\t\tvar win;\n\t\t\tif ( isWindow( elem ) ) {\n\t\t\t\twin = elem;\n\t\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t\twin = elem.defaultView;\n\t\t\t}\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : win.pageXOffset,\n\t\t\t\t\ttop ? val : win.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length );\n\t};\n} );\n\n// Support: Safari <=7 - 9.1, Chrome <=37 - 49\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347\n// getComputedStyle returns percent when specified for top/left/bottom/right;\n// rather than make the css module depend on the offset module, just check for it here\njQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\n\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n} );\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name },\n\t\tfunction( defaultExtra, funcName ) {\n\n\t\t// Margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( isWindow( elem ) ) {\n\n\t\t\t\t\t// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)\n\t\t\t\t\treturn funcName.indexOf( \"outer\" ) === 0 ?\n\t\t\t\t\t\telem[ \"inner\" + name ] :\n\t\t\t\t\t\telem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable );\n\t\t};\n\t} );\n} );\n\n\njQuery.each( ( \"blur focus focusin focusout resize scroll click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup contextmenu\" ).split( \" \" ),\n\tfunction( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n} );\n\njQuery.fn.extend( {\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n} );\n\n\n\n\njQuery.fn.extend( {\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ?\n\t\t\tthis.off( selector, \"**\" ) :\n\t\t\tthis.off( types, selector || \"**\", fn );\n\t}\n} );\n\n// Bind a function to a context, optionally partially applying any\n// arguments.\n// jQuery.proxy is deprecated to promote standards (specifically Function#bind)\n// However, it is not slated for removal any time soon\njQuery.proxy = function( fn, context ) {\n\tvar tmp, args, proxy;\n\n\tif ( typeof context === \"string\" ) {\n\t\ttmp = fn[ context ];\n\t\tcontext = fn;\n\t\tfn = tmp;\n\t}\n\n\t// Quick check to determine if target is callable, in the spec\n\t// this throws a TypeError, but we will just return undefined.\n\tif ( !isFunction( fn ) ) {\n\t\treturn undefined;\n\t}\n\n\t// Simulated bind\n\targs = slice.call( arguments, 2 );\n\tproxy = function() {\n\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t};\n\n\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\treturn proxy;\n};\n\njQuery.holdReady = function( hold ) {\n\tif ( hold ) {\n\t\tjQuery.readyWait++;\n\t} else {\n\t\tjQuery.ready( true );\n\t}\n};\njQuery.isArray = Array.isArray;\njQuery.parseJSON = JSON.parse;\njQuery.nodeName = nodeName;\njQuery.isFunction = isFunction;\njQuery.isWindow = isWindow;\njQuery.camelCase = camelCase;\njQuery.type = toType;\n\njQuery.now = Date.now;\n\njQuery.isNumeric = function( obj ) {\n\n\t// As of jQuery 3.0, isNumeric is limited to\n\t// strings and numbers (primitives or objects)\n\t// that can be coerced to finite numbers (gh-2662)\n\tvar type = jQuery.type( obj );\n\treturn ( type === \"number\" || type === \"string\" ) &&\n\n\t\t// parseFloat NaNs numeric-cast false positives (\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t!isNaN( obj - parseFloat( obj ) );\n};\n\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t} );\n}\n\n\n\n\nvar\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in AMD\n// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( !noGlobal ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n} );\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Scripts/jquery-3.4.1.slim.js",
    "content": "/*!\n * jQuery JavaScript Library v3.4.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector\n * https://jquery.com/\n *\n * Includes Sizzle.js\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://jquery.org/license\n *\n * Date: 2019-05-01T21:04Z\n */\n( function( global, factory ) {\n\n\t\"use strict\";\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n} )( typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1\n// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode\n// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common\n// enough that all such attempts are guarded in a try block.\n\"use strict\";\n\nvar arr = [];\n\nvar document = window.document;\n\nvar getProto = Object.getPrototypeOf;\n\nvar slice = arr.slice;\n\nvar concat = arr.concat;\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar fnToString = hasOwn.toString;\n\nvar ObjectFunctionString = fnToString.call( Object );\n\nvar support = {};\n\nvar isFunction = function isFunction( obj ) {\n\n      // Support: Chrome <=57, Firefox <=52\n      // In some browsers, typeof returns \"function\" for HTML <object> elements\n      // (i.e., `typeof document.createElement( \"object\" ) === \"function\"`).\n      // We don't want to classify *any* DOM node as a function.\n      return typeof obj === \"function\" && typeof obj.nodeType !== \"number\";\n  };\n\n\nvar isWindow = function isWindow( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t};\n\n\n\n\n\tvar preservedScriptAttributes = {\n\t\ttype: true,\n\t\tsrc: true,\n\t\tnonce: true,\n\t\tnoModule: true\n\t};\n\n\tfunction DOMEval( code, node, doc ) {\n\t\tdoc = doc || document;\n\n\t\tvar i, val,\n\t\t\tscript = doc.createElement( \"script\" );\n\n\t\tscript.text = code;\n\t\tif ( node ) {\n\t\t\tfor ( i in preservedScriptAttributes ) {\n\n\t\t\t\t// Support: Firefox 64+, Edge 18+\n\t\t\t\t// Some browsers don't support the \"nonce\" property on scripts.\n\t\t\t\t// On the other hand, just using `getAttribute` is not enough as\n\t\t\t\t// the `nonce` attribute is reset to an empty string whenever it\n\t\t\t\t// becomes browsing-context connected.\n\t\t\t\t// See https://github.com/whatwg/html/issues/2369\n\t\t\t\t// See https://html.spec.whatwg.org/#nonce-attributes\n\t\t\t\t// The `node.getAttribute` check was added for the sake of\n\t\t\t\t// `jQuery.globalEval` so that it can fake a nonce-containing node\n\t\t\t\t// via an object.\n\t\t\t\tval = node[ i ] || node.getAttribute && node.getAttribute( i );\n\t\t\t\tif ( val ) {\n\t\t\t\t\tscript.setAttribute( i, val );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tdoc.head.appendChild( script ).parentNode.removeChild( script );\n\t}\n\n\nfunction toType( obj ) {\n\tif ( obj == null ) {\n\t\treturn obj + \"\";\n\t}\n\n\t// Support: Android <=2.3 only (functionish RegExp)\n\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\tclass2type[ toString.call( obj ) ] || \"object\" :\n\t\ttypeof obj;\n}\n/* global Symbol */\n// Defining this global in .eslintrc.json would create a danger of using the global\n// unguarded in another place, it seems safer to define global only for this module\n\n\n\nvar\n\tversion = \"3.4.1 -ajax,-ajax/jsonp,-ajax/load,-ajax/parseXML,-ajax/script,-ajax/var/location,-ajax/var/nonce,-ajax/var/rquery,-ajax/xhr,-manipulation/_evalUrl,-event/ajax,-effects,-effects/Tween,-effects/animatedSelector\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Support: Android <=4.0 only\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;\n\njQuery.fn = jQuery.prototype = {\n\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\n\t\t// Return all the elements in a clean array\n\t\tif ( num == null ) {\n\t\t\treturn slice.call( this );\n\t\t}\n\n\t\t// Return just the one element from the set\n\t\treturn num < 0 ? this[ num + this.length ] : this[ num ];\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\teach: function( callback ) {\n\t\treturn jQuery.each( this, callback );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map( this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t} ) );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor();\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[ 0 ] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// Skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !isFunction( target ) ) {\n\t\ttarget = {};\n\t}\n\n\t// Extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\n\t\t// Only deal with non-null/undefined values\n\t\tif ( ( options = arguments[ i ] ) != null ) {\n\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent Object.prototype pollution\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( name === \"__proto__\" || target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject( copy ) ||\n\t\t\t\t\t( copyIsArray = Array.isArray( copy ) ) ) ) {\n\t\t\t\t\tsrc = target[ name ];\n\n\t\t\t\t\t// Ensure proper type for the source value\n\t\t\t\t\tif ( copyIsArray && !Array.isArray( src ) ) {\n\t\t\t\t\t\tclone = [];\n\t\t\t\t\t} else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {\n\t\t\t\t\t\tclone = {};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src;\n\t\t\t\t\t}\n\t\t\t\t\tcopyIsArray = false;\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend( {\n\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\tisPlainObject: function( obj ) {\n\t\tvar proto, Ctor;\n\n\t\t// Detect obvious negatives\n\t\t// Use toString instead of jQuery.type to catch host objects\n\t\tif ( !obj || toString.call( obj ) !== \"[object Object]\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tproto = getProto( obj );\n\n\t\t// Objects with no prototype (e.g., `Object.create( null )`) are plain\n\t\tif ( !proto ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Objects with prototype are plain iff they were constructed by a global Object function\n\t\tCtor = hasOwn.call( proto, \"constructor\" ) && proto.constructor;\n\t\treturn typeof Ctor === \"function\" && fnToString.call( Ctor ) === ObjectFunctionString;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( code, options ) {\n\t\tDOMEval( code, { nonce: options && options.nonce } );\n\t},\n\n\teach: function( obj, callback ) {\n\t\tvar length, i = 0;\n\n\t\tif ( isArrayLike( obj ) ) {\n\t\t\tlength = obj.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( i in obj ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Support: Android <=4.0 only\n\ttrim: function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArrayLike( Object( arr ) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t},\n\n\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t// push.apply(_, arraylike) throws on ancient WebKit\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar length, value,\n\t\t\ti = 0,\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArrayLike( elems ) ) {\n\t\t\tlength = elems.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n} );\n\nif ( typeof Symbol === \"function\" ) {\n\tjQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];\n}\n\n// Populate the class2type map\njQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".split( \" \" ),\nfunction( i, name ) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n} );\n\nfunction isArrayLike( obj ) {\n\n\t// Support: real iOS 8.2 only (not reproducible in simulator)\n\t// `in` check used to prevent JIT error (gh-2145)\n\t// hasOwn isn't used here due to false negatives\n\t// regarding Nodelist length in IE\n\tvar length = !!obj && \"length\" in obj && obj.length,\n\t\ttype = toType( obj );\n\n\tif ( isFunction( obj ) || isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.3.4\n * https://sizzlejs.com/\n *\n * Copyright JS Foundation and other contributors\n * Released under the MIT license\n * https://js.foundation/\n *\n * Date: 2019-04-08\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tnonnativeSelectorCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// https://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\n\t// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = \"(?:\\\\\\\\.|[\\\\w-]|[^\\0-\\\\xa0])+\",\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace +\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\"*\\\\]\",\n\n\tpseudos = \":(\" + identifier + \")(?:\\\\((\" +\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\trdescend = new RegExp( whitespace + \"|>\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + identifier + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + identifier + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + identifier + \"|[*])\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trhtml = /HTML$/i,\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\n\t// CSS escapes\n\t// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// CSS string/identifier serialization\n\t// https://drafts.csswg.org/cssom/#common-serializing-idioms\n\trcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,\n\tfcssescape = function( ch, asCodePoint ) {\n\t\tif ( asCodePoint ) {\n\n\t\t\t// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\n\t\t\tif ( ch === \"\\0\" ) {\n\t\t\t\treturn \"\\uFFFD\";\n\t\t\t}\n\n\t\t\t// Control characters and (dependent upon position) numbers get escaped as code points\n\t\t\treturn ch.slice( 0, -1 ) + \"\\\\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + \" \";\n\t\t}\n\n\t\t// Other potentially-special ASCII characters get backslash-escaped\n\t\treturn \"\\\\\" + ch;\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t},\n\n\tinDisabledFieldset = addCombinator(\n\t\tfunction( elem ) {\n\t\t\treturn elem.disabled === true && elem.nodeName.toLowerCase() === \"fieldset\";\n\t\t},\n\t\t{ dir: \"parentNode\", next: \"legend\" }\n\t);\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar m, i, elem, nid, match, groups, newSelector,\n\t\tnewContext = context && context.ownerDocument,\n\n\t\t// nodeType defaults to 9, since context defaults to document\n\t\tnodeType = context ? context.nodeType : 9;\n\n\tresults = results || [];\n\n\t// Return early from calls with invalid selector or context\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\t// Try to shortcut find operations (as opposed to filters) in HTML documents\n\tif ( !seed ) {\n\n\t\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\t\tsetDocument( context );\n\t\t}\n\t\tcontext = context || document;\n\n\t\tif ( documentIsHTML ) {\n\n\t\t\t// If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n\t\t\t// (excepting DocumentFragment context, where the methods don't exist)\n\t\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\n\t\t\t\t// ID selector\n\t\t\t\tif ( (m = match[1]) ) {\n\n\t\t\t\t\t// Document context\n\t\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\t\tif ( (elem = context.getElementById( m )) ) {\n\n\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// Element context\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\tif ( newContext && (elem = newContext.getElementById( m )) &&\n\t\t\t\t\t\t\tcontains( context, elem ) &&\n\t\t\t\t\t\t\telem.id === m ) {\n\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t// Type selector\n\t\t\t\t} else if ( match[2] ) {\n\t\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\t\treturn results;\n\n\t\t\t\t// Class selector\n\t\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName &&\n\t\t\t\t\tcontext.getElementsByClassName ) {\n\n\t\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Take advantage of querySelectorAll\n\t\t\tif ( support.qsa &&\n\t\t\t\t!nonnativeSelectorCache[ selector + \" \" ] &&\n\t\t\t\t(!rbuggyQSA || !rbuggyQSA.test( selector )) &&\n\n\t\t\t\t// Support: IE 8 only\n\t\t\t\t// Exclude object elements\n\t\t\t\t(nodeType !== 1 || context.nodeName.toLowerCase() !== \"object\") ) {\n\n\t\t\t\tnewSelector = selector;\n\t\t\t\tnewContext = context;\n\n\t\t\t\t// qSA considers elements outside a scoping root when evaluating child or\n\t\t\t\t// descendant combinators, which is not what we want.\n\t\t\t\t// In such cases, we work around the behavior by prefixing every selector in the\n\t\t\t\t// list with an ID selector referencing the scope context.\n\t\t\t\t// Thanks to Andrew Dupont for this technique.\n\t\t\t\tif ( nodeType === 1 && rdescend.test( selector ) ) {\n\n\t\t\t\t\t// Capture the context ID, setting it first if necessary\n\t\t\t\t\tif ( (nid = context.getAttribute( \"id\" )) ) {\n\t\t\t\t\t\tnid = nid.replace( rcssescape, fcssescape );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", (nid = expando) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prefix every selector in the list\n\t\t\t\t\tgroups = tokenize( selector );\n\t\t\t\t\ti = groups.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tgroups[i] = \"#\" + nid + \" \" + toSelector( groups[i] );\n\t\t\t\t\t}\n\t\t\t\t\tnewSelector = groups.join( \",\" );\n\n\t\t\t\t\t// Expand context for sibling selectors\n\t\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\tcontext;\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch ( qsaError ) {\n\t\t\t\t\tnonnativeSelectorCache( selector, true );\n\t\t\t\t} finally {\n\t\t\t\t\tif ( nid === expando ) {\n\t\t\t\t\t\tcontext.removeAttribute( \"id\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {function(string, object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created element and returns a boolean result\n */\nfunction assert( fn ) {\n\tvar el = document.createElement(\"fieldset\");\n\n\ttry {\n\t\treturn !!fn( el );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( el.parentNode ) {\n\t\t\tel.parentNode.removeChild( el );\n\t\t}\n\t\t// release memory in IE\n\t\tel = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = arr.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\ta.sourceIndex - b.sourceIndex;\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for :enabled/:disabled\n * @param {Boolean} disabled true for :disabled; false for :enabled\n */\nfunction createDisabledPseudo( disabled ) {\n\n\t// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable\n\treturn function( elem ) {\n\n\t\t// Only certain elements can match :enabled or :disabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled\n\t\tif ( \"form\" in elem ) {\n\n\t\t\t// Check for inherited disabledness on relevant non-disabled elements:\n\t\t\t// * listed form-associated elements in a disabled fieldset\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#category-listed\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled\n\t\t\t// * option elements in a disabled optgroup\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled\n\t\t\t// All such elements have a \"form\" property.\n\t\t\tif ( elem.parentNode && elem.disabled === false ) {\n\n\t\t\t\t// Option elements defer to a parent optgroup if present\n\t\t\t\tif ( \"label\" in elem ) {\n\t\t\t\t\tif ( \"label\" in elem.parentNode ) {\n\t\t\t\t\t\treturn elem.parentNode.disabled === disabled;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.disabled === disabled;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Support: IE 6 - 11\n\t\t\t\t// Use the isDisabled shortcut property to check for disabled fieldset ancestors\n\t\t\t\treturn elem.isDisabled === disabled ||\n\n\t\t\t\t\t// Where there is no isDisabled, check manually\n\t\t\t\t\t/* jshint -W018 */\n\t\t\t\t\telem.isDisabled !== !disabled &&\n\t\t\t\t\t\tinDisabledFieldset( elem ) === disabled;\n\t\t\t}\n\n\t\t\treturn elem.disabled === disabled;\n\n\t\t// Try to winnow out elements that can't be disabled before trusting the disabled property.\n\t\t// Some victims get caught in our net (label, legend, menu, track), but it shouldn't\n\t\t// even exist on them, let alone have a boolean value.\n\t\t} else if ( \"label\" in elem ) {\n\t\t\treturn elem.disabled === disabled;\n\t\t}\n\n\t\t// Remaining elements are neither :enabled nor :disabled\n\t\treturn false;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\tvar namespace = elem.namespaceURI,\n\t\tdocElem = (elem.ownerDocument || elem).documentElement;\n\n\t// Support: IE <=8\n\t// Assume HTML when documentElement doesn't yet exist, such as inside loading iframes\n\t// https://bugs.jquery.com/ticket/4833\n\treturn !rhtml.test( namespace || docElem && docElem.nodeName || \"HTML\" );\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, subWindow,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// Return early if doc is invalid or already selected\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Update global variables\n\tdocument = doc;\n\tdocElem = document.documentElement;\n\tdocumentIsHTML = !isXML( document );\n\n\t// Support: IE 9-11, Edge\n\t// Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n\tif ( preferredDoc !== document &&\n\t\t(subWindow = document.defaultView) && subWindow.top !== subWindow ) {\n\n\t\t// Support: IE 11, Edge\n\t\tif ( subWindow.addEventListener ) {\n\t\t\tsubWindow.addEventListener( \"unload\", unloadHandler, false );\n\n\t\t// Support: IE 9 - 10 only\n\t\t} else if ( subWindow.attachEvent ) {\n\t\t\tsubWindow.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert(function( el ) {\n\t\tel.className = \"i\";\n\t\treturn !el.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( el ) {\n\t\tel.appendChild( document.createComment(\"\") );\n\t\treturn !el.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( document.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programmatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( el ) {\n\t\tdocElem.appendChild( el ).id = expando;\n\t\treturn !document.getElementsByName || !document.getElementsByName( expando ).length;\n\t});\n\n\t// ID filter and find\n\tif ( support.getById ) {\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar elem = context.getElementById( id );\n\t\t\t\treturn elem ? [ elem ] : [];\n\t\t\t}\n\t\t};\n\t} else {\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" &&\n\t\t\t\t\telem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\n\t\t// Support: IE 6 - 7 only\n\t\t// getElementById is not reliable as a find shortcut\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar node, i, elems,\n\t\t\t\t\telem = context.getElementById( id );\n\n\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t// Verify the id attribute\n\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fall back on getElementsByName\n\t\t\t\t\telems = context.getElementsByName( id );\n\t\t\t\t\ti = 0;\n\t\t\t\t\twhile ( (elem = elems[i++]) ) {\n\t\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn [];\n\t\t\t}\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See https://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( document.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( el ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// https://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( el ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\r\\\\' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( el.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !el.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\t\t\tif ( !el.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !el.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibling-combinator selector` fails\n\t\t\tif ( !el.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( el ) {\n\t\t\tel.innerHTML = \"<a href='' disabled='disabled'></a>\" +\n\t\t\t\t\"<select disabled='disabled'><option/></select>\";\n\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = document.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tel.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( el.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( el.querySelectorAll(\":enabled\").length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// IE's :disabled selector does not pick up the children of disabled fieldsets\n\t\t\tdocElem.appendChild( el ).disabled = true;\n\t\t\tif ( el.querySelectorAll(\":disabled\").length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tel.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( el ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( el, \"*\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( el, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully self-exclusive\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === document ? -1 :\n\t\t\t\tb === document ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn document;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t!nonnativeSelectorCache[ expr + \" \" ] &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tnonnativeSelectorCache( expr, true );\n\t\t}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.escape = function( sel ) {\n\treturn (sel + \"\").replace( rcssescape, fcssescape );\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, uniqueCache, outerCache, node, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType,\n\t\t\t\t\t\tdiff = false;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) {\n\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\n\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\tnode = parent;\n\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\tdiff = nodeIndex && cache[ 2 ];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\tdiff = nodeIndex;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// xml :nth-child(...)\n\t\t\t\t\t\t\t// or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t\tif ( diff === false ) {\n\t\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t\tif ( ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) &&\n\t\t\t\t\t\t\t\t\t\t++diff ) {\n\n\t\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[0] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": createDisabledPseudo( false ),\n\t\t\"disabled\": createDisabledPseudo( true ),\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ?\n\t\t\t\targument + length :\n\t\t\t\targument > length ?\n\t\t\t\t\tlength :\n\t\t\t\t\targument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tskip = combinator.next,\n\t\tkey = skip || dir,\n\t\tcheckNonElements = base && key === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, uniqueCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\n\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\tuniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});\n\n\t\t\t\t\t\tif ( skip && skip === elem.nodeName.toLowerCase() ) {\n\t\t\t\t\t\t\telem = elem[ dir ] || elem;\n\t\t\t\t\t\t} else if ( (oldCache = uniqueCache[ key ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\tuniqueCache[ key ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context === document || context || outermost;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\tif ( !context && elem.ownerDocument !== document ) {\n\t\t\t\t\t\tsetDocument( elem );\n\t\t\t\t\t\txml = !documentIsHTML;\n\t\t\t\t\t}\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context || document, xml) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// `i` is now the count of elements visited above, and adding it to `matchedCount`\n\t\t\t// makes the latter nonnegative.\n\t\t\tmatchedCount += i;\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\t// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n\t\t\t// equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n\t\t\t// no element matchers and no seed.\n\t\t\t// Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n\t\t\t// case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n\t\t\t// numerically zero.\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is only one selector in the list and no seed\n\t// (the latter of which guarantees us context)\n\tif ( match.length === 1 ) {\n\n\t\t// Reduce context if the leading compound selector is an ID\n\t\ttokens = match[0] = match[0].slice( 0 );\n\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\tcontext.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\t!context || rsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( el ) {\n\t// Should return 1, but returns 4 (following)\n\treturn el.compareDocumentPosition( document.createElement(\"fieldset\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( el ) {\n\tel.innerHTML = \"<a href='#'></a>\";\n\treturn el.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( el ) {\n\tel.innerHTML = \"<input/>\";\n\tel.firstChild.setAttribute( \"value\", \"\" );\n\treturn el.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( el ) {\n\treturn el.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\nreturn Sizzle;\n\n})( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\n\n// Deprecated\njQuery.expr[ \":\" ] = jQuery.expr.pseudos;\njQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\njQuery.escapeSelector = Sizzle.escape;\n\n\n\n\nvar dir = function( elem, dir, until ) {\n\tvar matched = [],\n\t\ttruncate = until !== undefined;\n\n\twhile ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmatched.push( elem );\n\t\t}\n\t}\n\treturn matched;\n};\n\n\nvar siblings = function( n, elem ) {\n\tvar matched = [];\n\n\tfor ( ; n; n = n.nextSibling ) {\n\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\tmatched.push( n );\n\t\t}\n\t}\n\n\treturn matched;\n};\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\n\n\nfunction nodeName( elem, name ) {\n\n  return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\n};\nvar rsingleTag = ( /^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i );\n\n\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t} );\n\t}\n\n\t// Single element\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t} );\n\t}\n\n\t// Arraylike of elements (jQuery, arguments, Array)\n\tif ( typeof qualifier !== \"string\" ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not;\n\t\t} );\n\t}\n\n\t// Filtered directly for both simple and complex selectors\n\treturn jQuery.filter( qualifier, elements, not );\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\tif ( elems.length === 1 && elem.nodeType === 1 ) {\n\t\treturn jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];\n\t}\n\n\treturn jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\treturn elem.nodeType === 1;\n\t} ) );\n};\n\njQuery.fn.extend( {\n\tfind: function( selector ) {\n\t\tvar i, ret,\n\t\t\tlen = this.length,\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter( function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} ) );\n\t\t}\n\n\t\tret = this.pushStack( [] );\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\treturn len > 1 ? jQuery.uniqueSort( ret ) : ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], false ) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], true ) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n} );\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\t// Shortcut simple #id case for speed\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/,\n\n\tinit = jQuery.fn.init = function( selector, context, root ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Method init() accepts an alternate rootjQuery\n\t\t// so migrate can support jQuery.sub (gh-2101)\n\t\troot = root || rootjQuery;\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[ 0 ] === \"<\" &&\n\t\t\t\tselector[ selector.length - 1 ] === \">\" &&\n\t\t\t\tselector.length >= 3 ) {\n\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && ( match[ 1 ] || !context ) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[ 1 ] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[ 0 ] : context;\n\n\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[ 1 ],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[ 2 ] );\n\n\t\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis[ 0 ] = elem;\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || root ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis[ 0 ] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( isFunction( selector ) ) {\n\t\t\treturn root.ready !== undefined ?\n\t\t\t\troot.ready( selector ) :\n\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\n\t// Methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend( {\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter( function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[ i ] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\ttargets = typeof selectors !== \"string\" && jQuery( selectors );\n\n\t\t// Positional selectors never match, since there's no _selection_ context\n\t\tif ( !rneedsContext.test( selectors ) ) {\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tfor ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {\n\n\t\t\t\t\t// Always skip document fragments\n\t\t\t\t\tif ( cur.nodeType < 11 && ( targets ?\n\t\t\t\t\t\ttargets.index( cur ) > -1 :\n\n\t\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\t\tjQuery.find.matchesSelector( cur, selectors ) ) ) {\n\n\t\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within the set\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// Index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.uniqueSort(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t}\n} );\n\nfunction sibling( cur, dir ) {\n\twhile ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}\n\treturn cur;\n}\n\njQuery.each( {\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn siblings( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn siblings( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\tif ( typeof elem.contentDocument !== \"undefined\" ) {\n\t\t\treturn elem.contentDocument;\n\t\t}\n\n\t\t// Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only\n\t\t// Treat the template element as a regular one in browsers that\n\t\t// don't support it.\n\t\tif ( nodeName( elem, \"template\" ) ) {\n\t\t\telem = elem.content || elem;\n\t\t}\n\n\t\treturn jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.uniqueSort( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n} );\nvar rnothtmlwhite = ( /[^\\x20\\t\\r\\n\\f]+/g );\n\n\n\n// Convert String-formatted options into Object-formatted ones\nfunction createOptions( options ) {\n\tvar object = {};\n\tjQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t} );\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\tcreateOptions( options ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\n\t\t// Last fire value for non-forgettable lists\n\t\tmemory,\n\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\n\t\t// Flag to prevent firing\n\t\tlocked,\n\n\t\t// Actual callback list\n\t\tlist = [],\n\n\t\t// Queue of execution data for repeatable lists\n\t\tqueue = [],\n\n\t\t// Index of currently firing callback (modified by add/remove as needed)\n\t\tfiringIndex = -1,\n\n\t\t// Fire callbacks\n\t\tfire = function() {\n\n\t\t\t// Enforce single-firing\n\t\t\tlocked = locked || options.once;\n\n\t\t\t// Execute callbacks for all pending executions,\n\t\t\t// respecting firingIndex overrides and runtime changes\n\t\t\tfired = firing = true;\n\t\t\tfor ( ; queue.length; firingIndex = -1 ) {\n\t\t\t\tmemory = queue.shift();\n\t\t\t\twhile ( ++firingIndex < list.length ) {\n\n\t\t\t\t\t// Run callback and check for early termination\n\t\t\t\t\tif ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&\n\t\t\t\t\t\toptions.stopOnFalse ) {\n\n\t\t\t\t\t\t// Jump to end and forget the data so .add doesn't re-fire\n\t\t\t\t\t\tfiringIndex = list.length;\n\t\t\t\t\t\tmemory = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Forget the data if we're done with it\n\t\t\tif ( !options.memory ) {\n\t\t\t\tmemory = false;\n\t\t\t}\n\n\t\t\tfiring = false;\n\n\t\t\t// Clean up if we're done firing for good\n\t\t\tif ( locked ) {\n\n\t\t\t\t// Keep an empty list if we have data for future add calls\n\t\t\t\tif ( memory ) {\n\t\t\t\t\tlist = [];\n\n\t\t\t\t// Otherwise, this object is spent\n\t\t\t\t} else {\n\t\t\t\t\tlist = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Actual Callbacks object\n\t\tself = {\n\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\n\t\t\t\t\t// If we have memory from a past run, we should fire after adding\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfiringIndex = list.length - 1;\n\t\t\t\t\t\tqueue.push( memory );\n\t\t\t\t\t}\n\n\t\t\t\t\t( function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tif ( isFunction( arg ) ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && toType( arg ) !== \"string\" ) {\n\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\t\t\t\t\t} )( arguments );\n\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\tvar index;\n\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\tlist.splice( index, 1 );\n\n\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ?\n\t\t\t\t\tjQuery.inArray( fn, list ) > -1 :\n\t\t\t\t\tlist.length > 0;\n\t\t\t},\n\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Disable .fire and .add\n\t\t\t// Abort any current/pending executions\n\t\t\t// Clear all callbacks and values\n\t\t\tdisable: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tlist = memory = \"\";\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\n\t\t\t// Disable .fire\n\t\t\t// Also disable .add unless we have memory (since it would have no effect)\n\t\t\t// Abort any pending executions\n\t\t\tlock: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tif ( !memory && !firing ) {\n\t\t\t\t\tlist = memory = \"\";\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tlocked: function() {\n\t\t\t\treturn !!locked;\n\t\t\t},\n\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( !locked ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tqueue.push( args );\n\t\t\t\t\tif ( !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\nfunction Identity( v ) {\n\treturn v;\n}\nfunction Thrower( ex ) {\n\tthrow ex;\n}\n\nfunction adoptValue( value, resolve, reject, noValue ) {\n\tvar method;\n\n\ttry {\n\n\t\t// Check for promise aspect first to privilege synchronous behavior\n\t\tif ( value && isFunction( ( method = value.promise ) ) ) {\n\t\t\tmethod.call( value ).done( resolve ).fail( reject );\n\n\t\t// Other thenables\n\t\t} else if ( value && isFunction( ( method = value.then ) ) ) {\n\t\t\tmethod.call( value, resolve, reject );\n\n\t\t// Other non-thenables\n\t\t} else {\n\n\t\t\t// Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:\n\t\t\t// * false: [ value ].slice( 0 ) => resolve( value )\n\t\t\t// * true: [ value ].slice( 1 ) => resolve()\n\t\t\tresolve.apply( undefined, [ value ].slice( noValue ) );\n\t\t}\n\n\t// For Promises/A+, convert exceptions into rejections\n\t// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in\n\t// Deferred#then to conditionally suppress rejection.\n\t} catch ( value ) {\n\n\t\t// Support: Android 4.0 only\n\t\t// Strict mode functions invoked without .call/.apply get global-object context\n\t\treject.apply( undefined, [ value ] );\n\t}\n}\n\njQuery.extend( {\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\n\t\t\t\t// action, add listener, callbacks,\n\t\t\t\t// ... .then handlers, argument index, [final state]\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks( \"memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"memory\" ), 2 ],\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 0, \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 1, \"rejected\" ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\t\"catch\": function( fn ) {\n\t\t\t\t\treturn promise.then( null, fn );\n\t\t\t\t},\n\n\t\t\t\t// Keep pipe for back-compat\n\t\t\t\tpipe: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\n\t\t\t\t\t\t\t// Map tuples (progress, done, fail) to arguments (done, fail, progress)\n\t\t\t\t\t\t\tvar fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];\n\n\t\t\t\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\t\t\t\t// deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\n\t\t\t\t\t\t\tdeferred[ tuple[ 1 ] ]( function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify )\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\t\t\t\tthen: function( onFulfilled, onRejected, onProgress ) {\n\t\t\t\t\tvar maxDepth = 0;\n\t\t\t\t\tfunction resolve( depth, deferred, handler, special ) {\n\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\tvar that = this,\n\t\t\t\t\t\t\t\targs = arguments,\n\t\t\t\t\t\t\t\tmightThrow = function() {\n\t\t\t\t\t\t\t\t\tvar returned, then;\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.3\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-59\n\t\t\t\t\t\t\t\t\t// Ignore double-resolution attempts\n\t\t\t\t\t\t\t\t\tif ( depth < maxDepth ) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturned = handler.apply( that, args );\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.1\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-48\n\t\t\t\t\t\t\t\t\tif ( returned === deferred.promise() ) {\n\t\t\t\t\t\t\t\t\t\tthrow new TypeError( \"Thenable self-resolution\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ sections 2.3.3.1, 3.5\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-54\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-75\n\t\t\t\t\t\t\t\t\t// Retrieve `then` only once\n\t\t\t\t\t\t\t\t\tthen = returned &&\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.4\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-64\n\t\t\t\t\t\t\t\t\t\t// Only check objects and functions for thenability\n\t\t\t\t\t\t\t\t\t\t( typeof returned === \"object\" ||\n\t\t\t\t\t\t\t\t\t\t\ttypeof returned === \"function\" ) &&\n\t\t\t\t\t\t\t\t\t\treturned.then;\n\n\t\t\t\t\t\t\t\t\t// Handle a returned thenable\n\t\t\t\t\t\t\t\t\tif ( isFunction( then ) ) {\n\n\t\t\t\t\t\t\t\t\t\t// Special processors (notify) just wait for resolution\n\t\t\t\t\t\t\t\t\t\tif ( special ) {\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special )\n\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t// Normal processors (resolve) also hook into progress\n\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t// ...and disregard older resolution values\n\t\t\t\t\t\t\t\t\t\t\tmaxDepth++;\n\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdeferred.notifyWith )\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Handle all other returned values\n\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\tif ( handler !== Identity ) {\n\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\targs = [ returned ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Process the value(s)\n\t\t\t\t\t\t\t\t\t\t// Default process is resolve\n\t\t\t\t\t\t\t\t\t\t( special || deferred.resolveWith )( that, args );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t// Only normal processors (resolve) catch and reject exceptions\n\t\t\t\t\t\t\t\tprocess = special ?\n\t\t\t\t\t\t\t\t\tmightThrow :\n\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tmightThrow();\n\t\t\t\t\t\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t\t\t\t\t\tif ( jQuery.Deferred.exceptionHook ) {\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery.Deferred.exceptionHook( e,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprocess.stackTrace );\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.4.1\n\t\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-61\n\t\t\t\t\t\t\t\t\t\t\t// Ignore post-resolution exceptions\n\t\t\t\t\t\t\t\t\t\t\tif ( depth + 1 >= maxDepth ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\t\t\tif ( handler !== Thrower ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\t\t\targs = [ e ];\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tdeferred.rejectWith( that, args );\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.1\n\t\t\t\t\t\t\t// https://promisesaplus.com/#point-57\n\t\t\t\t\t\t\t// Re-resolve promises immediately to dodge false rejection from\n\t\t\t\t\t\t\t// subsequent errors\n\t\t\t\t\t\t\tif ( depth ) {\n\t\t\t\t\t\t\t\tprocess();\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// Call an optional hook to record the stack, in case of exception\n\t\t\t\t\t\t\t\t// since it's otherwise lost when execution goes async\n\t\t\t\t\t\t\t\tif ( jQuery.Deferred.getStackHook ) {\n\t\t\t\t\t\t\t\t\tprocess.stackTrace = jQuery.Deferred.getStackHook();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twindow.setTimeout( process );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\n\t\t\t\t\t\t// progress_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 0 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onProgress ) ?\n\t\t\t\t\t\t\t\t\tonProgress :\n\t\t\t\t\t\t\t\t\tIdentity,\n\t\t\t\t\t\t\t\tnewDefer.notifyWith\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// fulfilled_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 1 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onFulfilled ) ?\n\t\t\t\t\t\t\t\t\tonFulfilled :\n\t\t\t\t\t\t\t\t\tIdentity\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// rejected_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 2 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tisFunction( onRejected ) ?\n\t\t\t\t\t\t\t\t\tonRejected :\n\t\t\t\t\t\t\t\t\tThrower\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 5 ];\n\n\t\t\t// promise.progress = list.add\n\t\t\t// promise.done = list.add\n\t\t\t// promise.fail = list.add\n\t\t\tpromise[ tuple[ 1 ] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(\n\t\t\t\t\tfunction() {\n\n\t\t\t\t\t\t// state = \"resolved\" (i.e., fulfilled)\n\t\t\t\t\t\t// state = \"rejected\"\n\t\t\t\t\t\tstate = stateString;\n\t\t\t\t\t},\n\n\t\t\t\t\t// rejected_callbacks.disable\n\t\t\t\t\t// fulfilled_callbacks.disable\n\t\t\t\t\ttuples[ 3 - i ][ 2 ].disable,\n\n\t\t\t\t\t// rejected_handlers.disable\n\t\t\t\t\t// fulfilled_handlers.disable\n\t\t\t\t\ttuples[ 3 - i ][ 3 ].disable,\n\n\t\t\t\t\t// progress_callbacks.lock\n\t\t\t\t\ttuples[ 0 ][ 2 ].lock,\n\n\t\t\t\t\t// progress_handlers.lock\n\t\t\t\t\ttuples[ 0 ][ 3 ].lock\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// progress_handlers.fire\n\t\t\t// fulfilled_handlers.fire\n\t\t\t// rejected_handlers.fire\n\t\t\tlist.add( tuple[ 3 ].fire );\n\n\t\t\t// deferred.notify = function() { deferred.notifyWith(...) }\n\t\t\t// deferred.resolve = function() { deferred.resolveWith(...) }\n\t\t\t// deferred.reject = function() { deferred.rejectWith(...) }\n\t\t\tdeferred[ tuple[ 0 ] ] = function() {\n\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ]( this === deferred ? undefined : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\n\t\t\t// deferred.notifyWith = list.fireWith\n\t\t\t// deferred.resolveWith = list.fireWith\n\t\t\t// deferred.rejectWith = list.fireWith\n\t\t\tdeferred[ tuple[ 0 ] + \"With\" ] = list.fireWith;\n\t\t} );\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( singleValue ) {\n\t\tvar\n\n\t\t\t// count of uncompleted subordinates\n\t\t\tremaining = arguments.length,\n\n\t\t\t// count of unprocessed arguments\n\t\t\ti = remaining,\n\n\t\t\t// subordinate fulfillment data\n\t\t\tresolveContexts = Array( i ),\n\t\t\tresolveValues = slice.call( arguments ),\n\n\t\t\t// the master Deferred\n\t\t\tmaster = jQuery.Deferred(),\n\n\t\t\t// subordinate callback factory\n\t\t\tupdateFunc = function( i ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tresolveContexts[ i ] = this;\n\t\t\t\t\tresolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( !( --remaining ) ) {\n\t\t\t\t\t\tmaster.resolveWith( resolveContexts, resolveValues );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\n\t\t// Single- and empty arguments are adopted like Promise.resolve\n\t\tif ( remaining <= 1 ) {\n\t\t\tadoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,\n\t\t\t\t!remaining );\n\n\t\t\t// Use .then() to unwrap secondary thenables (cf. gh-3000)\n\t\t\tif ( master.state() === \"pending\" ||\n\t\t\t\tisFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {\n\n\t\t\t\treturn master.then();\n\t\t\t}\n\t\t}\n\n\t\t// Multiple arguments are aggregated like Promise.all array elements\n\t\twhile ( i-- ) {\n\t\t\tadoptValue( resolveValues[ i ], updateFunc( i ), master.reject );\n\t\t}\n\n\t\treturn master.promise();\n\t}\n} );\n\n\n// These usually indicate a programmer mistake during development,\n// warn about them ASAP rather than swallowing them by default.\nvar rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;\n\njQuery.Deferred.exceptionHook = function( error, stack ) {\n\n\t// Support: IE 8 - 9 only\n\t// Console exists when dev tools are open, which can happen at any time\n\tif ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {\n\t\twindow.console.warn( \"jQuery.Deferred exception: \" + error.message, error.stack, stack );\n\t}\n};\n\n\n\n\njQuery.readyException = function( error ) {\n\twindow.setTimeout( function() {\n\t\tthrow error;\n\t} );\n};\n\n\n\n\n// The deferred used on DOM ready\nvar readyList = jQuery.Deferred();\n\njQuery.fn.ready = function( fn ) {\n\n\treadyList\n\t\t.then( fn )\n\n\t\t// Wrap jQuery.readyException in a function so that the lookup\n\t\t// happens at the time of error handling instead of callback\n\t\t// registration.\n\t\t.catch( function( error ) {\n\t\t\tjQuery.readyException( error );\n\t\t} );\n\n\treturn this;\n};\n\njQuery.extend( {\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\t}\n} );\n\njQuery.ready.then = readyList.then;\n\n// The ready event handler and self cleanup method\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed );\n\twindow.removeEventListener( \"load\", completed );\n\tjQuery.ready();\n}\n\n// Catch cases where $(document).ready() is called\n// after the browser event has already occurred.\n// Support: IE <=9 - 10 only\n// Older IE sometimes signals \"interactive\" too soon\nif ( document.readyState === \"complete\" ||\n\t( document.readyState !== \"loading\" && !document.documentElement.doScroll ) ) {\n\n\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\twindow.setTimeout( jQuery.ready );\n\n} else {\n\n\t// Use the handy event callback\n\tdocument.addEventListener( \"DOMContentLoaded\", completed );\n\n\t// A fallback to window.onload, that will always work\n\twindow.addEventListener( \"load\", completed );\n}\n\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( toType( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\taccess( elems, fn, i, key[ i ], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tfn(\n\t\t\t\t\telems[ i ], key, raw ?\n\t\t\t\t\tvalue :\n\t\t\t\t\tvalue.call( elems[ i ], i, fn( elems[ i ], key ) )\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( chainable ) {\n\t\treturn elems;\n\t}\n\n\t// Gets\n\tif ( bulk ) {\n\t\treturn fn.call( elems );\n\t}\n\n\treturn len ? fn( elems[ 0 ], key ) : emptyGet;\n};\n\n\n// Matches dashed string for camelizing\nvar rmsPrefix = /^-ms-/,\n\trdashAlpha = /-([a-z])/g;\n\n// Used by camelCase as callback to replace()\nfunction fcamelCase( all, letter ) {\n\treturn letter.toUpperCase();\n}\n\n// Convert dashed to camelCase; used by the css and data modules\n// Support: IE <=9 - 11, Edge 12 - 15\n// Microsoft forgot to hump their vendor prefix (#9572)\nfunction camelCase( string ) {\n\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n}\nvar acceptData = function( owner ) {\n\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\n\n\nfunction Data() {\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\n\nData.prototype = {\n\n\tcache: function( owner ) {\n\n\t\t// Check if the owner object already has a cache\n\t\tvar value = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !value ) {\n\t\t\tvalue = {};\n\n\t\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t\t// but we should not, see #8335.\n\t\t\t// Always return an empty object.\n\t\t\tif ( acceptData( owner ) ) {\n\n\t\t\t\t// If it is a node unlikely to be stringify-ed or looped over\n\t\t\t\t// use plain assignment\n\t\t\t\tif ( owner.nodeType ) {\n\t\t\t\t\towner[ this.expando ] = value;\n\n\t\t\t\t// Otherwise secure it in a non-enumerable property\n\t\t\t\t// configurable must be true to allow the property to be\n\t\t\t\t// deleted when data is removed\n\t\t\t\t} else {\n\t\t\t\t\tObject.defineProperty( owner, this.expando, {\n\t\t\t\t\t\tvalue: value,\n\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn value;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\tcache = this.cache( owner );\n\n\t\t// Handle: [ owner, key, value ] args\n\t\t// Always use camelCase key (gh-2257)\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ camelCase( data ) ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\n\t\t\t// Copy the properties one-by-one to the cache object\n\t\t\tfor ( prop in data ) {\n\t\t\t\tcache[ camelCase( prop ) ] = data[ prop ];\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\treturn key === undefined ?\n\t\t\tthis.cache( owner ) :\n\n\t\t\t// Always use camelCase key (gh-2257)\n\t\t\towner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];\n\t},\n\taccess: function( owner, key, value ) {\n\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t( ( key && typeof key === \"string\" ) && value === undefined ) ) {\n\n\t\t\treturn this.get( owner, key );\n\t\t}\n\n\t\t// When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i,\n\t\t\tcache = owner[ this.expando ];\n\n\t\tif ( cache === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key !== undefined ) {\n\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( Array.isArray( key ) ) {\n\n\t\t\t\t// If key is an array of keys...\n\t\t\t\t// We always set camelCase keys, so remove that.\n\t\t\t\tkey = key.map( camelCase );\n\t\t\t} else {\n\t\t\t\tkey = camelCase( key );\n\n\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\tkey = key in cache ?\n\t\t\t\t\t[ key ] :\n\t\t\t\t\t( key.match( rnothtmlwhite ) || [] );\n\t\t\t}\n\n\t\t\ti = key.length;\n\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ key[ i ] ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if there's no more data\n\t\tif ( key === undefined || jQuery.isEmptyObject( cache ) ) {\n\n\t\t\t// Support: Chrome <=35 - 45\n\t\t\t// Webkit & Blink performance suffers when deleting properties\n\t\t\t// from DOM nodes, so set to undefined instead\n\t\t\t// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)\n\t\t\tif ( owner.nodeType ) {\n\t\t\t\towner[ this.expando ] = undefined;\n\t\t\t} else {\n\t\t\t\tdelete owner[ this.expando ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\tvar cache = owner[ this.expando ];\n\t\treturn cache !== undefined && !jQuery.isEmptyObject( cache );\n\t}\n};\nvar dataPriv = new Data();\n\nvar dataUser = new Data();\n\n\n\n//\tImplementation Summary\n//\n//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n//\t2. Improve the module's maintainability by reducing the storage\n//\t\tpaths to a single mechanism.\n//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /[A-Z]/g;\n\nfunction getData( data ) {\n\tif ( data === \"true\" ) {\n\t\treturn true;\n\t}\n\n\tif ( data === \"false\" ) {\n\t\treturn false;\n\t}\n\n\tif ( data === \"null\" ) {\n\t\treturn null;\n\t}\n\n\t// Only convert to a number if it doesn't change the string\n\tif ( data === +data + \"\" ) {\n\t\treturn +data;\n\t}\n\n\tif ( rbrace.test( data ) ) {\n\t\treturn JSON.parse( data );\n\t}\n\n\treturn data;\n}\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$&\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = getData( data );\n\t\t\t} catch ( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdataUser.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend( {\n\thasData: function( elem ) {\n\t\treturn dataUser.hasData( elem ) || dataPriv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn dataUser.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdataUser.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to dataPriv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn dataPriv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdataPriv.remove( elem, name );\n\t}\n} );\n\njQuery.fn.extend( {\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = dataUser.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !dataPriv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE 11 only\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = camelCase( name.slice( 5 ) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdataPriv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tdataUser.set( this, key );\n\t\t\t} );\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data;\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// The key will always be camelCased in Data\n\t\t\t\tdata = dataUser.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each( function() {\n\n\t\t\t\t// We always store the camelCased key\n\t\t\t\tdataUser.set( this, key, value );\n\t\t\t} );\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each( function() {\n\t\t\tdataUser.remove( this, key );\n\t\t} );\n\t}\n} );\n\n\njQuery.extend( {\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = dataPriv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || Array.isArray( data ) ) {\n\t\t\t\t\tqueue = dataPriv.access( elem, type, jQuery.makeArray( data ) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// Clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// Not public - generate a queueHooks object, or return the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn dataPriv.get( elem, key ) || dataPriv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks( \"once memory\" ).add( function() {\n\t\t\t\tdataPriv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t} )\n\t\t} );\n\t}\n} );\n\njQuery.fn.extend( {\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[ 0 ], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each( function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[ 0 ] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t} );\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t} );\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = dataPriv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n} );\nvar pnum = ( /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/ ).source;\n\nvar rcssNum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" );\n\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar documentElement = document.documentElement;\n\n\n\n\tvar isAttached = function( elem ) {\n\t\t\treturn jQuery.contains( elem.ownerDocument, elem );\n\t\t},\n\t\tcomposed = { composed: true };\n\n\t// Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only\n\t// Check attachment across shadow DOM boundaries when possible (gh-3504)\n\t// Support: iOS 10.0-10.2 only\n\t// Early iOS 10 versions support `attachShadow` but not `getRootNode`,\n\t// leading to errors. We need to check for `getRootNode`.\n\tif ( documentElement.getRootNode ) {\n\t\tisAttached = function( elem ) {\n\t\t\treturn jQuery.contains( elem.ownerDocument, elem ) ||\n\t\t\t\telem.getRootNode( composed ) === elem.ownerDocument;\n\t\t};\n\t}\nvar isHiddenWithinTree = function( elem, el ) {\n\n\t\t// isHiddenWithinTree might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\n\t\t// Inline style trumps all\n\t\treturn elem.style.display === \"none\" ||\n\t\t\telem.style.display === \"\" &&\n\n\t\t\t// Otherwise, check computed style\n\t\t\t// Support: Firefox <=43 - 45\n\t\t\t// Disconnected elements can have computed display: none, so first confirm that elem is\n\t\t\t// in the document.\n\t\t\tisAttached( elem ) &&\n\n\t\t\tjQuery.css( elem, \"display\" ) === \"none\";\n\t};\n\nvar swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\n\n\nfunction adjustCSS( elem, prop, valueParts, tween ) {\n\tvar adjusted, scale,\n\t\tmaxIterations = 20,\n\t\tcurrentValue = tween ?\n\t\t\tfunction() {\n\t\t\t\treturn tween.cur();\n\t\t\t} :\n\t\t\tfunction() {\n\t\t\t\treturn jQuery.css( elem, prop, \"\" );\n\t\t\t},\n\t\tinitial = currentValue(),\n\t\tunit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t// Starting value computation is required for potential unit mismatches\n\t\tinitialInUnit = elem.nodeType &&\n\t\t\t( jQuery.cssNumber[ prop ] || unit !== \"px\" && +initial ) &&\n\t\t\trcssNum.exec( jQuery.css( elem, prop ) );\n\n\tif ( initialInUnit && initialInUnit[ 3 ] !== unit ) {\n\n\t\t// Support: Firefox <=54\n\t\t// Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144)\n\t\tinitial = initial / 2;\n\n\t\t// Trust units reported by jQuery.css\n\t\tunit = unit || initialInUnit[ 3 ];\n\n\t\t// Iteratively approximate from a nonzero starting point\n\t\tinitialInUnit = +initial || 1;\n\n\t\twhile ( maxIterations-- ) {\n\n\t\t\t// Evaluate and update our best guess (doubling guesses that zero out).\n\t\t\t// Finish if the scale equals or crosses 1 (making the old*new product non-positive).\n\t\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\t\t\tif ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) {\n\t\t\t\tmaxIterations = 0;\n\t\t\t}\n\t\t\tinitialInUnit = initialInUnit / scale;\n\n\t\t}\n\n\t\tinitialInUnit = initialInUnit * 2;\n\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\n\t\t// Make sure we update the tween properties later on\n\t\tvalueParts = valueParts || [];\n\t}\n\n\tif ( valueParts ) {\n\t\tinitialInUnit = +initialInUnit || +initial || 0;\n\n\t\t// Apply relative offset (+=/-=) if specified\n\t\tadjusted = valueParts[ 1 ] ?\n\t\t\tinitialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :\n\t\t\t+valueParts[ 2 ];\n\t\tif ( tween ) {\n\t\t\ttween.unit = unit;\n\t\t\ttween.start = initialInUnit;\n\t\t\ttween.end = adjusted;\n\t\t}\n\t}\n\treturn adjusted;\n}\n\n\nvar defaultDisplayMap = {};\n\nfunction getDefaultDisplay( elem ) {\n\tvar temp,\n\t\tdoc = elem.ownerDocument,\n\t\tnodeName = elem.nodeName,\n\t\tdisplay = defaultDisplayMap[ nodeName ];\n\n\tif ( display ) {\n\t\treturn display;\n\t}\n\n\ttemp = doc.body.appendChild( doc.createElement( nodeName ) );\n\tdisplay = jQuery.css( temp, \"display\" );\n\n\ttemp.parentNode.removeChild( temp );\n\n\tif ( display === \"none\" ) {\n\t\tdisplay = \"block\";\n\t}\n\tdefaultDisplayMap[ nodeName ] = display;\n\n\treturn display;\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\t// Determine new display value for elements that need to change\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\n\t\t\t// Since we force visibility upon cascade-hidden elements, an immediate (and slow)\n\t\t\t// check is required in this first loop unless we have a nonempty display value (either\n\t\t\t// inline or about-to-be-restored)\n\t\t\tif ( display === \"none\" ) {\n\t\t\t\tvalues[ index ] = dataPriv.get( elem, \"display\" ) || null;\n\t\t\t\tif ( !values[ index ] ) {\n\t\t\t\t\telem.style.display = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( elem.style.display === \"\" && isHiddenWithinTree( elem ) ) {\n\t\t\t\tvalues[ index ] = getDefaultDisplay( elem );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( display !== \"none\" ) {\n\t\t\t\tvalues[ index ] = \"none\";\n\n\t\t\t\t// Remember what we're overwriting\n\t\t\t\tdataPriv.set( elem, \"display\", display );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of the elements in a second loop to avoid constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\tif ( values[ index ] != null ) {\n\t\t\telements[ index ].style.display = values[ index ];\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend( {\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tif ( isHiddenWithinTree( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t} );\n\t}\n} );\nvar rcheckableType = ( /^(?:checkbox|radio)$/i );\n\nvar rtagName = ( /<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)/i );\n\nvar rscriptType = ( /^$|^module$|\\/(?:java|ecma)script/i );\n\n\n\n// We have to close these tags to support XHTML (#13200)\nvar wrapMap = {\n\n\t// Support: IE <=9 only\n\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t// XHTML parsers do not magically insert elements in the\n\t// same way that tag soup parsers do. So we cannot shorten\n\t// this by omitting <tbody> or other required elements.\n\tthead: [ 1, \"<table>\", \"</table>\" ],\n\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t_default: [ 0, \"\", \"\" ]\n};\n\n// Support: IE <=9 only\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n\nfunction getAll( context, tag ) {\n\n\t// Support: IE <=9 - 11 only\n\t// Use typeof to avoid zero-argument method invocation on host objects (#15151)\n\tvar ret;\n\n\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\tret = context.getElementsByTagName( tag || \"*\" );\n\n\t} else if ( typeof context.querySelectorAll !== \"undefined\" ) {\n\t\tret = context.querySelectorAll( tag || \"*\" );\n\n\t} else {\n\t\tret = [];\n\t}\n\n\tif ( tag === undefined || tag && nodeName( context, tag ) ) {\n\t\treturn jQuery.merge( [ context ], ret );\n\t}\n\n\treturn ret;\n}\n\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdataPriv.set(\n\t\t\telems[ i ],\n\t\t\t\"globalEval\",\n\t\t\t!refElements || dataPriv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\n\nvar rhtml = /<|&#?\\w+;/;\n\nfunction buildFragment( elems, context, scripts, selection, ignored ) {\n\tvar elem, tmp, tag, wrap, attached, j,\n\t\tfragment = context.createDocumentFragment(),\n\t\tnodes = [],\n\t\ti = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\telem = elems[ i ];\n\n\t\tif ( elem || elem === 0 ) {\n\n\t\t\t// Add nodes directly\n\t\t\tif ( toType( elem ) === \"object\" ) {\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t// Convert non-html into a text node\n\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t// Convert html into DOM nodes\n\t\t\t} else {\n\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement( \"div\" ) );\n\n\t\t\t\t// Deserialize a standard representation\n\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\ttmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];\n\n\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\tj = wrap[ 0 ];\n\t\t\t\twhile ( j-- ) {\n\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t}\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t// Remember the top-level container\n\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\ttmp.textContent = \"\";\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove wrapper from fragment\n\tfragment.textContent = \"\";\n\n\ti = 0;\n\twhile ( ( elem = nodes[ i++ ] ) ) {\n\n\t\t// Skip elements already in the context collection (trac-4087)\n\t\tif ( selection && jQuery.inArray( elem, selection ) > -1 ) {\n\t\t\tif ( ignored ) {\n\t\t\t\tignored.push( elem );\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tattached = isAttached( elem );\n\n\t\t// Append to fragment\n\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t// Preserve script evaluation history\n\t\tif ( attached ) {\n\t\t\tsetGlobalEval( tmp );\n\t\t}\n\n\t\t// Capture executables\n\t\tif ( scripts ) {\n\t\t\tj = 0;\n\t\t\twhile ( ( elem = tmp[ j++ ] ) ) {\n\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\tscripts.push( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fragment;\n}\n\n\n( function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Support: Android 4.0 - 4.3 only\n\t// Check state lost if the name is set (#11217)\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Android <=4.1 only\n\t// Older WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE <=11 only\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n} )();\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n// Support: IE <=9 - 11+\n// focus() and blur() are asynchronous, except when they are no-op.\n// So expect focus to be synchronous when the element is already active,\n// and blur to be synchronous when the element is not already active.\n// (focus and blur are always synchronous in other supported browsers,\n// this just defines when we can count on it).\nfunction expectSync( elem, type ) {\n\treturn ( elem === safeActiveElement() ) === ( type === \"focus\" );\n}\n\n// Support: IE <=9 only\n// Accessing document.activeElement can throw unexpectedly\n// https://bugs.jquery.com/ticket/13393\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\nfunction on( elem, types, selector, data, fn, one ) {\n\tvar origFn, type;\n\n\t// Types can be a map of types/handlers\n\tif ( typeof types === \"object\" ) {\n\n\t\t// ( types-Object, selector, data )\n\t\tif ( typeof selector !== \"string\" ) {\n\n\t\t\t// ( types-Object, data )\n\t\t\tdata = data || selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tfor ( type in types ) {\n\t\t\ton( elem, type, selector, data, types[ type ], one );\n\t\t}\n\t\treturn elem;\n\t}\n\n\tif ( data == null && fn == null ) {\n\n\t\t// ( types, fn )\n\t\tfn = selector;\n\t\tdata = selector = undefined;\n\t} else if ( fn == null ) {\n\t\tif ( typeof selector === \"string\" ) {\n\n\t\t\t// ( types, selector, fn )\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t} else {\n\n\t\t\t// ( types, data, fn )\n\t\t\tfn = data;\n\t\t\tdata = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t}\n\tif ( fn === false ) {\n\t\tfn = returnFalse;\n\t} else if ( !fn ) {\n\t\treturn elem;\n\t}\n\n\tif ( one === 1 ) {\n\t\torigFn = fn;\n\t\tfn = function( event ) {\n\n\t\t\t// Can use an empty set, since event contains the info\n\t\t\tjQuery().off( event );\n\t\t\treturn origFn.apply( this, arguments );\n\t\t};\n\n\t\t// Use same guid so caller can remove using origFn\n\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t}\n\treturn elem.each( function() {\n\t\tjQuery.event.add( this, types, fn, data, selector );\n\t} );\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.get( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Ensure that invalid selectors throw exceptions at attach time\n\t\t// Evaluate against documentElement in case elem is a non-element node (e.g., document)\n\t\tif ( selector ) {\n\t\t\tjQuery.find.matchesSelector( documentElement, selector );\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !( events = elemData.events ) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !( eventHandle = elemData.handle ) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend( {\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join( \".\" )\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !( handlers = events[ type ] ) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\tif ( !special.setup ||\n\t\t\t\t\tspecial.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.hasData( elem ) && dataPriv.get( elem );\n\n\t\tif ( !elemData || !( events = elemData.events ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[ 2 ] &&\n\t\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector ||\n\t\t\t\t\t\tselector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown ||\n\t\t\t\t\tspecial.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove data and the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdataPriv.remove( elem, \"handle events\" );\n\t\t}\n\t},\n\n\tdispatch: function( nativeEvent ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tvar event = jQuery.event.fix( nativeEvent );\n\n\t\tvar i, j, ret, matched, handleObj, handlerQueue,\n\t\t\targs = new Array( arguments.length ),\n\t\t\thandlers = ( dataPriv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[ 0 ] = event;\n\n\t\tfor ( i = 1; i < arguments.length; i++ ) {\n\t\t\targs[ i ] = arguments[ i ];\n\t\t}\n\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( ( handleObj = matched.handlers[ j++ ] ) &&\n\t\t\t\t!event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// If the event is namespaced, then each handler is only invoked if it is\n\t\t\t\t// specially universal or its namespaces are a superset of the event's.\n\t\t\t\tif ( !event.rnamespace || handleObj.namespace === false ||\n\t\t\t\t\tevent.rnamespace.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||\n\t\t\t\t\t\thandleObj.handler ).apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( ( event.result = ret ) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, handleObj, sel, matchedHandlers, matchedSelectors,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\tif ( delegateCount &&\n\n\t\t\t// Support: IE <=9\n\t\t\t// Black-hole SVG <use> instance trees (trac-13180)\n\t\t\tcur.nodeType &&\n\n\t\t\t// Support: Firefox <=42\n\t\t\t// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n\t\t\t// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n\t\t\t// Support: IE 11 only\n\t\t\t// ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n\t\t\t!( event.type === \"click\" && event.button >= 1 ) ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && !( event.type === \"click\" && cur.disabled === true ) ) {\n\t\t\t\t\tmatchedHandlers = [];\n\t\t\t\t\tmatchedSelectors = {};\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatchedSelectors[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) > -1 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] ) {\n\t\t\t\t\t\t\tmatchedHandlers.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matchedHandlers.length ) {\n\t\t\t\t\t\thandlerQueue.push( { elem: cur, handlers: matchedHandlers } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tcur = this;\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\taddProp: function( name, hook ) {\n\t\tObject.defineProperty( jQuery.Event.prototype, name, {\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\n\t\t\tget: isFunction( hook ) ?\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn hook( this.originalEvent );\n\t\t\t\t\t}\n\t\t\t\t} :\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn this.originalEvent[ name ];\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\tset: function( value ) {\n\t\t\t\tObject.defineProperty( this, name, {\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: value\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t},\n\n\tfix: function( originalEvent ) {\n\t\treturn originalEvent[ jQuery.expando ] ?\n\t\t\toriginalEvent :\n\t\t\tnew jQuery.Event( originalEvent );\n\t},\n\n\tspecial: {\n\t\tload: {\n\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tclick: {\n\n\t\t\t// Utilize native event to ensure correct state for checkable inputs\n\t\t\tsetup: function( data ) {\n\n\t\t\t\t// For mutual compressibility with _default, replace `this` access with a local var.\n\t\t\t\t// `|| data` is dead code meant only to preserve the variable through minification.\n\t\t\t\tvar el = this || data;\n\n\t\t\t\t// Claim the first handler\n\t\t\t\tif ( rcheckableType.test( el.type ) &&\n\t\t\t\t\tel.click && nodeName( el, \"input\" ) ) {\n\n\t\t\t\t\t// dataPriv.set( el, \"click\", ... )\n\t\t\t\t\tleverageNative( el, \"click\", returnTrue );\n\t\t\t\t}\n\n\t\t\t\t// Return false to allow normal processing in the caller\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\ttrigger: function( data ) {\n\n\t\t\t\t// For mutual compressibility with _default, replace `this` access with a local var.\n\t\t\t\t// `|| data` is dead code meant only to preserve the variable through minification.\n\t\t\t\tvar el = this || data;\n\n\t\t\t\t// Force setup before triggering a click\n\t\t\t\tif ( rcheckableType.test( el.type ) &&\n\t\t\t\t\tel.click && nodeName( el, \"input\" ) ) {\n\n\t\t\t\t\tleverageNative( el, \"click\" );\n\t\t\t\t}\n\n\t\t\t\t// Return non-false to allow normal event-path propagation\n\t\t\t\treturn true;\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, suppress native .click() on links\n\t\t\t// Also prevent it if we're currently inside a leveraged native-event stack\n\t\t\t_default: function( event ) {\n\t\t\t\tvar target = event.target;\n\t\t\t\treturn rcheckableType.test( target.type ) &&\n\t\t\t\t\ttarget.click && nodeName( target, \"input\" ) &&\n\t\t\t\t\tdataPriv.get( target, \"click\" ) ||\n\t\t\t\t\tnodeName( target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Ensure the presence of an event listener that handles manually-triggered\n// synthetic events by interrupting progress until reinvoked in response to\n// *native* events that it fires directly, ensuring that state changes have\n// already occurred before other listeners are invoked.\nfunction leverageNative( el, type, expectSync ) {\n\n\t// Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add\n\tif ( !expectSync ) {\n\t\tif ( dataPriv.get( el, type ) === undefined ) {\n\t\t\tjQuery.event.add( el, type, returnTrue );\n\t\t}\n\t\treturn;\n\t}\n\n\t// Register the controller as a special universal handler for all event namespaces\n\tdataPriv.set( el, type, false );\n\tjQuery.event.add( el, type, {\n\t\tnamespace: false,\n\t\thandler: function( event ) {\n\t\t\tvar notAsync, result,\n\t\t\t\tsaved = dataPriv.get( this, type );\n\n\t\t\tif ( ( event.isTrigger & 1 ) && this[ type ] ) {\n\n\t\t\t\t// Interrupt processing of the outer synthetic .trigger()ed event\n\t\t\t\t// Saved data should be false in such cases, but might be a leftover capture object\n\t\t\t\t// from an async native handler (gh-4350)\n\t\t\t\tif ( !saved.length ) {\n\n\t\t\t\t\t// Store arguments for use when handling the inner native event\n\t\t\t\t\t// There will always be at least one argument (an event object), so this array\n\t\t\t\t\t// will not be confused with a leftover capture object.\n\t\t\t\t\tsaved = slice.call( arguments );\n\t\t\t\t\tdataPriv.set( this, type, saved );\n\n\t\t\t\t\t// Trigger the native event and capture its result\n\t\t\t\t\t// Support: IE <=9 - 11+\n\t\t\t\t\t// focus() and blur() are asynchronous\n\t\t\t\t\tnotAsync = expectSync( this, type );\n\t\t\t\t\tthis[ type ]();\n\t\t\t\t\tresult = dataPriv.get( this, type );\n\t\t\t\t\tif ( saved !== result || notAsync ) {\n\t\t\t\t\t\tdataPriv.set( this, type, false );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = {};\n\t\t\t\t\t}\n\t\t\t\t\tif ( saved !== result ) {\n\n\t\t\t\t\t\t// Cancel the outer synthetic event\n\t\t\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\treturn result.value;\n\t\t\t\t\t}\n\n\t\t\t\t// If this is an inner synthetic event for an event with a bubbling surrogate\n\t\t\t\t// (focus or blur), assume that the surrogate already propagated from triggering the\n\t\t\t\t// native event and prevent that from happening again here.\n\t\t\t\t// This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the\n\t\t\t\t// bubbling surrogate propagates *after* the non-bubbling base), but that seems\n\t\t\t\t// less bad than duplication.\n\t\t\t\t} else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t}\n\n\t\t\t// If this is a native event triggered above, everything is now in order\n\t\t\t// Fire an inner synthetic event with the original arguments\n\t\t\t} else if ( saved.length ) {\n\n\t\t\t\t// ...and capture the result\n\t\t\t\tdataPriv.set( this, type, {\n\t\t\t\t\tvalue: jQuery.event.trigger(\n\n\t\t\t\t\t\t// Support: IE <=9 - 11+\n\t\t\t\t\t\t// Extend with the prototype to reset the above stopImmediatePropagation()\n\t\t\t\t\t\tjQuery.extend( saved[ 0 ], jQuery.Event.prototype ),\n\t\t\t\t\t\tsaved.slice( 1 ),\n\t\t\t\t\t\tthis\n\t\t\t\t\t)\n\t\t\t\t} );\n\n\t\t\t\t// Abort handling of the native event\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t}\n\t\t}\n\t} );\n}\n\njQuery.removeEvent = function( elem, type, handle ) {\n\n\t// This \"if\" is needed for plain objects\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\n\t// Allow instantiation without the 'new' keyword\n\tif ( !( this instanceof jQuery.Event ) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\n\t\t\t\t// Support: Android <=2.3 only\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t\t// Create target properties\n\t\t// Support: Safari <=6 - 7 only\n\t\t// Target should not be a text node (#504, #13143)\n\t\tthis.target = ( src.target && src.target.nodeType === 3 ) ?\n\t\t\tsrc.target.parentNode :\n\t\t\tsrc.target;\n\n\t\tthis.currentTarget = src.currentTarget;\n\t\tthis.relatedTarget = src.relatedTarget;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || Date.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tconstructor: jQuery.Event,\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\tisSimulated: false,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Includes all common event props including KeyEvent and MouseEvent specific props\njQuery.each( {\n\taltKey: true,\n\tbubbles: true,\n\tcancelable: true,\n\tchangedTouches: true,\n\tctrlKey: true,\n\tdetail: true,\n\teventPhase: true,\n\tmetaKey: true,\n\tpageX: true,\n\tpageY: true,\n\tshiftKey: true,\n\tview: true,\n\t\"char\": true,\n\tcode: true,\n\tcharCode: true,\n\tkey: true,\n\tkeyCode: true,\n\tbutton: true,\n\tbuttons: true,\n\tclientX: true,\n\tclientY: true,\n\toffsetX: true,\n\toffsetY: true,\n\tpointerId: true,\n\tpointerType: true,\n\tscreenX: true,\n\tscreenY: true,\n\ttargetTouches: true,\n\ttoElement: true,\n\ttouches: true,\n\n\twhich: function( event ) {\n\t\tvar button = event.button;\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && rkeyEvent.test( event.type ) ) {\n\t\t\treturn event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\tif ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {\n\t\t\tif ( button & 1 ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tif ( button & 2 ) {\n\t\t\t\treturn 3;\n\t\t\t}\n\n\t\t\tif ( button & 4 ) {\n\t\t\t\treturn 2;\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn event.which;\n\t}\n}, jQuery.event.addProp );\n\njQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( type, delegateType ) {\n\tjQuery.event.special[ type ] = {\n\n\t\t// Utilize native event if possible so blur/focus sequence is correct\n\t\tsetup: function() {\n\n\t\t\t// Claim the first handler\n\t\t\t// dataPriv.set( this, \"focus\", ... )\n\t\t\t// dataPriv.set( this, \"blur\", ... )\n\t\t\tleverageNative( this, type, expectSync );\n\n\t\t\t// Return false to allow normal processing in the caller\n\t\t\treturn false;\n\t\t},\n\t\ttrigger: function() {\n\n\t\t\t// Force setup before trigger\n\t\t\tleverageNative( this, type );\n\n\t\t\t// Return non-false to allow normal event-path propagation\n\t\t\treturn true;\n\t\t},\n\n\t\tdelegateType: delegateType\n\t};\n} );\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// so that event delegation works in jQuery.\n// Do the same for pointerenter/pointerleave and pointerover/pointerout\n//\n// Support: Safari 7 only\n// Safari sends mouseenter too often; see:\n// https://bugs.chromium.org/p/chromium/issues/detail?id=470258\n// for the description of the bug (it existed in older Chrome versions as well).\njQuery.each( {\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mouseenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n} );\n\njQuery.fn.extend( {\n\n\ton: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn );\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ?\n\t\t\t\t\thandleObj.origType + \".\" + handleObj.namespace :\n\t\t\t\t\thandleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t} );\n\t}\n} );\n\n\nvar\n\n\t/* eslint-disable max-len */\n\n\t// See https://github.com/eslint/eslint/issues/3229\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)[^>]*)\\/>/gi,\n\n\t/* eslint-enable */\n\n\t// Support: IE <=10 - 11, Edge 12 - 13 only\n\t// In IE/Edge using regex groups here causes severe slowdowns.\n\t// See https://connect.microsoft.com/IE/feedback/details/1736512/\n\trnoInnerhtml = /<script|<style|<link/i,\n\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g;\n\n// Prefer a tbody over its parent table for containing new rows\nfunction manipulationTarget( elem, content ) {\n\tif ( nodeName( elem, \"table\" ) &&\n\t\tnodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ) {\n\n\t\treturn jQuery( elem ).children( \"tbody\" )[ 0 ] || elem;\n\t}\n\n\treturn elem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = ( elem.getAttribute( \"type\" ) !== null ) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tif ( ( elem.type || \"\" ).slice( 0, 5 ) === \"true/\" ) {\n\t\telem.type = elem.type.slice( 5 );\n\t} else {\n\t\telem.removeAttribute( \"type\" );\n\t}\n\n\treturn elem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( dataPriv.hasData( src ) ) {\n\t\tpdataOld = dataPriv.access( src );\n\t\tpdataCur = dataPriv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( dataUser.hasData( src ) ) {\n\t\tudataOld = dataUser.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdataUser.set( dest, udataCur );\n\t}\n}\n\n// Fix IE bugs, see support tests\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\nfunction domManip( collection, args, callback, ignored ) {\n\n\t// Flatten any nested arrays\n\targs = concat.apply( [], args );\n\n\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\ti = 0,\n\t\tl = collection.length,\n\t\tiNoClone = l - 1,\n\t\tvalue = args[ 0 ],\n\t\tvalueIsFunction = isFunction( value );\n\n\t// We can't cloneNode fragments that contain checked, in WebKit\n\tif ( valueIsFunction ||\n\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\treturn collection.each( function( index ) {\n\t\t\tvar self = collection.eq( index );\n\t\t\tif ( valueIsFunction ) {\n\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t}\n\t\t\tdomManip( self, args, callback, ignored );\n\t\t} );\n\t}\n\n\tif ( l ) {\n\t\tfragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );\n\t\tfirst = fragment.firstChild;\n\n\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\tfragment = first;\n\t\t}\n\n\t\t// Require either new content or an interest in ignored elements to invoke the callback\n\t\tif ( first || ignored ) {\n\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\thasScripts = scripts.length;\n\n\t\t\t// Use the original fragment for the last item\n\t\t\t// instead of the first because it can end up\n\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tnode = fragment;\n\n\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\tif ( hasScripts ) {\n\n\t\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcallback.call( collection[ i ], node, i );\n\t\t\t}\n\n\t\t\tif ( hasScripts ) {\n\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t// Reenable scripts\n\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t!dataPriv.access( node, \"globalEval\" ) &&\n\t\t\t\t\t\tjQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\tif ( node.src && ( node.type || \"\" ).toLowerCase()  !== \"module\" ) {\n\n\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\tif ( jQuery._evalUrl && !node.noModule ) {\n\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src, {\n\t\t\t\t\t\t\t\t\tnonce: node.nonce || node.getAttribute( \"nonce\" )\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDOMEval( node.textContent.replace( rcleanScript, \"\" ), node, doc );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn collection;\n}\n\nfunction remove( elem, selector, keepData ) {\n\tvar node,\n\t\tnodes = selector ? jQuery.filter( selector, elem ) : elem,\n\t\ti = 0;\n\n\tfor ( ; ( node = nodes[ i ] ) != null; i++ ) {\n\t\tif ( !keepData && node.nodeType === 1 ) {\n\t\t\tjQuery.cleanData( getAll( node ) );\n\t\t}\n\n\t\tif ( node.parentNode ) {\n\t\t\tif ( keepData && isAttached( node ) ) {\n\t\t\t\tsetGlobalEval( getAll( node, \"script\" ) );\n\t\t\t}\n\t\t\tnode.parentNode.removeChild( node );\n\t\t}\n\t}\n\n\treturn elem;\n}\n\njQuery.extend( {\n\thtmlPrefilter: function( html ) {\n\t\treturn html.replace( rxhtmlTag, \"<$1></$2>\" );\n\t},\n\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = isAttached( elem );\n\n\t\t// Fix IE cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, type,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {\n\t\t\tif ( acceptData( elem ) ) {\n\t\t\t\tif ( ( data = elem[ dataPriv.expando ] ) ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataPriv.expando ] = undefined;\n\t\t\t\t}\n\t\t\t\tif ( elem[ dataUser.expando ] ) {\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataUser.expando ] = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n} );\n\njQuery.fn.extend( {\n\tdetach: function( selector ) {\n\t\treturn remove( this, selector, true );\n\t},\n\n\tremove: function( selector ) {\n\t\treturn remove( this, selector );\n\t},\n\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().each( function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t} );\n\t},\n\n\tprepend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t} );\n\t},\n\n\tbefore: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t} );\n\t},\n\n\tafter: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t} );\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = this[ i ] ) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t} );\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = jQuery.htmlPrefilter( value );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch ( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar ignored = [];\n\n\t\t// Make the changes, replacing each non-ignored context element with the new content\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tvar parent = this.parentNode;\n\n\t\t\tif ( jQuery.inArray( this, ignored ) < 0 ) {\n\t\t\t\tjQuery.cleanData( getAll( this ) );\n\t\t\t\tif ( parent ) {\n\t\t\t\t\tparent.replaceChild( elem, this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Force callback invocation\n\t\t}, ignored );\n\t}\n} );\n\njQuery.each( {\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t// .get() because push.apply(_, arraylike) throws on ancient WebKit\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n} );\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar getStyles = function( elem ) {\n\n\t\t// Support: IE <=11 only, Firefox <=30 (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tvar view = elem.ownerDocument.defaultView;\n\n\t\tif ( !view || !view.opener ) {\n\t\t\tview = window;\n\t\t}\n\n\t\treturn view.getComputedStyle( elem );\n\t};\n\nvar rboxStyle = new RegExp( cssExpand.join( \"|\" ), \"i\" );\n\n\n\n( function() {\n\n\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t// so they're executed at the same time to save the second computation.\n\tfunction computeStyleTests() {\n\n\t\t// This is a singleton, we need to execute it only once\n\t\tif ( !div ) {\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer.style.cssText = \"position:absolute;left:-11111px;width:60px;\" +\n\t\t\t\"margin-top:1px;padding:0;border:0\";\n\t\tdiv.style.cssText =\n\t\t\t\"position:relative;display:block;box-sizing:border-box;overflow:scroll;\" +\n\t\t\t\"margin:auto;border:1px;padding:1px;\" +\n\t\t\t\"width:60%;top:1%\";\n\t\tdocumentElement.appendChild( container ).appendChild( div );\n\n\t\tvar divStyle = window.getComputedStyle( div );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\n\t\t// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44\n\t\treliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12;\n\n\t\t// Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3\n\t\t// Some styles come back with percentage values, even though they shouldn't\n\t\tdiv.style.right = \"60%\";\n\t\tpixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36;\n\n\t\t// Support: IE 9 - 11 only\n\t\t// Detect misreporting of content dimensions for box-sizing:border-box elements\n\t\tboxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36;\n\n\t\t// Support: IE 9 only\n\t\t// Detect overflow:scroll screwiness (gh-3699)\n\t\t// Support: Chrome <=64\n\t\t// Don't get tricked when zoom affects offsetWidth (gh-4029)\n\t\tdiv.style.position = \"absolute\";\n\t\tscrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12;\n\n\t\tdocumentElement.removeChild( container );\n\n\t\t// Nullify the div so it wouldn't be stored in the memory and\n\t\t// it will also be a sign that checks already performed\n\t\tdiv = null;\n\t}\n\n\tfunction roundPixelMeasures( measure ) {\n\t\treturn Math.round( parseFloat( measure ) );\n\t}\n\n\tvar pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal,\n\t\treliableMarginLeftVal,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Finish early in limited (non-browser) environments\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE <=9 - 11 only\n\t// Style of cloned element affects source element cloned (#8908)\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tjQuery.extend( support, {\n\t\tboxSizingReliable: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\t\tpixelBoxStyles: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelBoxStylesVal;\n\t\t},\n\t\tpixelPosition: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelPositionVal;\n\t\t},\n\t\treliableMarginLeft: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn reliableMarginLeftVal;\n\t\t},\n\t\tscrollboxSize: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn scrollboxSizeVal;\n\t\t}\n\t} );\n} )();\n\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\n\t\t// Support: Firefox 51+\n\t\t// Retrieving style before computed somehow\n\t\t// fixes an issue with getting wrong values\n\t\t// on detached elements\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// getPropertyValue is needed for:\n\t//   .css('filter') (IE 9 only, #12537)\n\t//   .css('--customProperty) (#3144)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\n\t\tif ( ret === \"\" && !isAttached( elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// Android Browser returns percentage for some values,\n\t\t// but width seems to be reliably pixels.\n\t\t// This is against the CSSOM draft spec:\n\t\t// https://drafts.csswg.org/cssom/#resolved-values\n\t\tif ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret !== undefined ?\n\n\t\t// Support: IE <=9 - 11 only\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tif ( conditionFn() ) {\n\n\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t// to missing dependency), remove it.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\treturn ( this.get = hookFn ).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\nvar cssPrefixes = [ \"Webkit\", \"Moz\", \"ms\" ],\n\temptyStyle = document.createElement( \"div\" ).style,\n\tvendorProps = {};\n\n// Return a vendor-prefixed property or undefined\nfunction vendorPropName( name ) {\n\n\t// Check for vendor prefixed names\n\tvar capName = name[ 0 ].toUpperCase() + name.slice( 1 ),\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in emptyStyle ) {\n\t\t\treturn name;\n\t\t}\n\t}\n}\n\n// Return a potentially-mapped jQuery.cssProps or vendor prefixed property\nfunction finalPropName( name ) {\n\tvar final = jQuery.cssProps[ name ] || vendorProps[ name ];\n\n\tif ( final ) {\n\t\treturn final;\n\t}\n\tif ( name in emptyStyle ) {\n\t\treturn name;\n\t}\n\treturn vendorProps[ name ] = vendorPropName( name ) || name;\n}\n\n\nvar\n\n\t// Swappable if display is none or starts with table\n\t// except \"table\", \"table-cell\", or \"table-caption\"\n\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trcustomProp = /^--/,\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t};\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\n\t// Any relative (+/-) values have already been\n\t// normalized at this point\n\tvar matches = rcssNum.exec( value );\n\treturn matches ?\n\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) {\n\tvar i = dimension === \"width\" ? 1 : 0,\n\t\textra = 0,\n\t\tdelta = 0;\n\n\t// Adjustment may not be necessary\n\tif ( box === ( isBorderBox ? \"border\" : \"content\" ) ) {\n\t\treturn 0;\n\t}\n\n\tfor ( ; i < 4; i += 2 ) {\n\n\t\t// Both box models exclude margin\n\t\tif ( box === \"margin\" ) {\n\t\t\tdelta += jQuery.css( elem, box + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\t// If we get here with a content-box, we're seeking \"padding\" or \"border\" or \"margin\"\n\t\tif ( !isBorderBox ) {\n\n\t\t\t// Add padding\n\t\t\tdelta += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// For \"border\" or \"margin\", add border\n\t\t\tif ( box !== \"padding\" ) {\n\t\t\t\tdelta += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\n\t\t\t// But still keep track of it otherwise\n\t\t\t} else {\n\t\t\t\textra += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\n\t\t// If we get here with a border-box (content + padding + border), we're seeking \"content\" or\n\t\t// \"padding\" or \"margin\"\n\t\t} else {\n\n\t\t\t// For \"content\", subtract padding\n\t\t\tif ( box === \"content\" ) {\n\t\t\t\tdelta -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// For \"content\" or \"padding\", subtract border\n\t\t\tif ( box !== \"margin\" ) {\n\t\t\t\tdelta -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Account for positive content-box scroll gutter when requested by providing computedVal\n\tif ( !isBorderBox && computedVal >= 0 ) {\n\n\t\t// offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border\n\t\t// Assuming integer scroll gutter, subtract the rest and round down\n\t\tdelta += Math.max( 0, Math.ceil(\n\t\t\telem[ \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -\n\t\t\tcomputedVal -\n\t\t\tdelta -\n\t\t\textra -\n\t\t\t0.5\n\n\t\t// If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter\n\t\t// Use an explicit zero to avoid NaN (gh-3964)\n\t\t) ) || 0;\n\t}\n\n\treturn delta;\n}\n\nfunction getWidthOrHeight( elem, dimension, extra ) {\n\n\t// Start with computed style\n\tvar styles = getStyles( elem ),\n\n\t\t// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322).\n\t\t// Fake content-box until we know it's needed to know the true value.\n\t\tboxSizingNeeded = !support.boxSizingReliable() || extra,\n\t\tisBorderBox = boxSizingNeeded &&\n\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\tvalueIsBorderBox = isBorderBox,\n\n\t\tval = curCSS( elem, dimension, styles ),\n\t\toffsetProp = \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 );\n\n\t// Support: Firefox <=54\n\t// Return a confounding non-pixel value or feign ignorance, as appropriate.\n\tif ( rnumnonpx.test( val ) ) {\n\t\tif ( !extra ) {\n\t\t\treturn val;\n\t\t}\n\t\tval = \"auto\";\n\t}\n\n\n\t// Fall back to offsetWidth/offsetHeight when value is \"auto\"\n\t// This happens for inline elements with no explicit setting (gh-3571)\n\t// Support: Android <=4.1 - 4.3 only\n\t// Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602)\n\t// Support: IE 9-11 only\n\t// Also use offsetWidth/offsetHeight for when box sizing is unreliable\n\t// We use getClientRects() to check for hidden/disconnected.\n\t// In those cases, the computed value can be trusted to be border-box\n\tif ( ( !support.boxSizingReliable() && isBorderBox ||\n\t\tval === \"auto\" ||\n\t\t!parseFloat( val ) && jQuery.css( elem, \"display\", false, styles ) === \"inline\" ) &&\n\t\telem.getClientRects().length ) {\n\n\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t\t// Where available, offsetWidth/offsetHeight approximate border box dimensions.\n\t\t// Where not available (e.g., SVG), assume unreliable box-sizing and interpret the\n\t\t// retrieved value as a content box dimension.\n\t\tvalueIsBorderBox = offsetProp in elem;\n\t\tif ( valueIsBorderBox ) {\n\t\t\tval = elem[ offsetProp ];\n\t\t}\n\t}\n\n\t// Normalize \"\" and auto\n\tval = parseFloat( val ) || 0;\n\n\t// Adjust for the element's box model\n\treturn ( val +\n\t\tboxModelAdjustment(\n\t\t\telem,\n\t\t\tdimension,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles,\n\n\t\t\t// Provide the current computed size to request scroll gutter calculation (gh-3589)\n\t\t\tval\n\t\t)\n\t) + \"px\";\n}\n\njQuery.extend( {\n\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"animationIterationCount\": true,\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"gridArea\": true,\n\t\t\"gridColumn\": true,\n\t\t\"gridColumnEnd\": true,\n\t\t\"gridColumnStart\": true,\n\t\t\"gridRow\": true,\n\t\t\"gridRowEnd\": true,\n\t\t\"gridRowStart\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = camelCase( name ),\n\t\t\tisCustomProp = rcustomProp.test( name ),\n\t\t\tstyle = elem.style;\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to query the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\n\n\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\tif ( type === \"string\" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {\n\t\t\t\tvalue = adjustCSS( elem, name, ret );\n\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add the unit (except for certain CSS properties)\n\t\t\t// The isCustomProp check can be removed in jQuery 4.0 when we only auto-append\n\t\t\t// \"px\" to a few hardcoded values.\n\t\t\tif ( type === \"number\" && !isCustomProp ) {\n\t\t\t\tvalue += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? \"\" : \"px\" );\n\t\t\t}\n\n\t\t\t// background-* props affect original clone's values\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !( \"set\" in hooks ) ||\n\t\t\t\t( value = hooks.set( elem, value, extra ) ) !== undefined ) {\n\n\t\t\t\tif ( isCustomProp ) {\n\t\t\t\t\tstyle.setProperty( name, value );\n\t\t\t\t} else {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks &&\n\t\t\t\t( ret = hooks.get( elem, false, extra ) ) !== undefined ) {\n\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = camelCase( name ),\n\t\t\tisCustomProp = rcustomProp.test( name );\n\n\t\t// Make sure that we're working with the right name. We don't\n\t\t// want to modify the value if it is a CSS custom property\n\t\t// since they are user-defined.\n\t\tif ( !isCustomProp ) {\n\t\t\tname = finalPropName( origName );\n\t\t}\n\n\t\t// Try prefixed name followed by the unprefixed name\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t// Convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || isFinite( num ) ? num || 0 : val;\n\t\t}\n\n\t\treturn val;\n\t}\n} );\n\njQuery.each( [ \"height\", \"width\" ], function( i, dimension ) {\n\tjQuery.cssHooks[ dimension ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) &&\n\n\t\t\t\t\t// Support: Safari 8+\n\t\t\t\t\t// Table columns in Safari have non-zero offsetWidth & zero\n\t\t\t\t\t// getBoundingClientRect().width unless display is changed.\n\t\t\t\t\t// Support: IE <=11 only\n\t\t\t\t\t// Running getBoundingClientRect on a disconnected node\n\t\t\t\t\t// in IE throws an error.\n\t\t\t\t\t( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?\n\t\t\t\t\t\tswap( elem, cssShow, function() {\n\t\t\t\t\t\t\treturn getWidthOrHeight( elem, dimension, extra );\n\t\t\t\t\t\t} ) :\n\t\t\t\t\t\tgetWidthOrHeight( elem, dimension, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar matches,\n\t\t\t\tstyles = getStyles( elem ),\n\n\t\t\t\t// Only read styles.position if the test has a chance to fail\n\t\t\t\t// to avoid forcing a reflow.\n\t\t\t\tscrollboxSizeBuggy = !support.scrollboxSize() &&\n\t\t\t\t\tstyles.position === \"absolute\",\n\n\t\t\t\t// To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991)\n\t\t\t\tboxSizingNeeded = scrollboxSizeBuggy || extra,\n\t\t\t\tisBorderBox = boxSizingNeeded &&\n\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\tsubtract = extra ?\n\t\t\t\t\tboxModelAdjustment(\n\t\t\t\t\t\telem,\n\t\t\t\t\t\tdimension,\n\t\t\t\t\t\textra,\n\t\t\t\t\t\tisBorderBox,\n\t\t\t\t\t\tstyles\n\t\t\t\t\t) :\n\t\t\t\t\t0;\n\n\t\t\t// Account for unreliable border-box dimensions by comparing offset* to computed and\n\t\t\t// faking a content-box to get border and padding (gh-3699)\n\t\t\tif ( isBorderBox && scrollboxSizeBuggy ) {\n\t\t\t\tsubtract -= Math.ceil(\n\t\t\t\t\telem[ \"offset\" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -\n\t\t\t\t\tparseFloat( styles[ dimension ] ) -\n\t\t\t\t\tboxModelAdjustment( elem, dimension, \"border\", false, styles ) -\n\t\t\t\t\t0.5\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Convert to pixels if value adjustment is needed\n\t\t\tif ( subtract && ( matches = rcssNum.exec( value ) ) &&\n\t\t\t\t( matches[ 3 ] || \"px\" ) !== \"px\" ) {\n\n\t\t\t\telem.style[ dimension ] = value;\n\t\t\t\tvalue = jQuery.css( elem, dimension );\n\t\t\t}\n\n\t\t\treturn setPositiveNumber( elem, value, subtract );\n\t\t}\n\t};\n} );\n\njQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn ( parseFloat( curCSS( elem, \"marginLeft\" ) ) ||\n\t\t\t\telem.getBoundingClientRect().left -\n\t\t\t\t\tswap( elem, { marginLeft: 0 }, function() {\n\t\t\t\t\t\treturn elem.getBoundingClientRect().left;\n\t\t\t\t\t} )\n\t\t\t\t) + \"px\";\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each( {\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// Assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split( \" \" ) : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( prefix !== \"margin\" ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n} );\n\njQuery.fn.extend( {\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( Array.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t}\n} );\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = window.setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\twindow.clearTimeout( timeout );\n\t\t};\n\t} );\n};\n\n\n( function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\tinput.type = \"checkbox\";\n\n\t// Support: Android <=4.3 only\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE <=11 only\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: IE <=11 only\n\t// An input loses its value after becoming a radio\n\tinput = document.createElement( \"input\" );\n\tinput.value = \"t\";\n\tinput.type = \"radio\";\n\tsupport.radioValue = input.value === \"t\";\n} )();\n\n\nvar boolHook,\n\tattrHandle = jQuery.expr.attrHandle;\n\njQuery.fn.extend( {\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tattr: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set attributes on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// Attribute hooks are determined by the lowercase version\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\thooks = jQuery.attrHooks[ name.toLowerCase() ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\treturn value;\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tret = jQuery.find.attr( elem, name );\n\n\t\t// Non-existent attributes return null, we normalize to undefined\n\t\treturn ret == null ? undefined : ret;\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\tnodeName( elem, \"input\" ) ) {\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name,\n\t\t\ti = 0,\n\n\t\t\t// Attribute names can contain non-HTML whitespace characters\n\t\t\t// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n\t\t\tattrNames = value && value.match( rnothtmlwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( ( name = attrNames[ i++ ] ) ) {\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\n\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar ret, handle,\n\t\t\tlowercaseName = name.toLowerCase();\n\n\t\tif ( !isXML ) {\n\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ lowercaseName ];\n\t\t\tattrHandle[ lowercaseName ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tlowercaseName :\n\t\t\t\tnull;\n\t\t\tattrHandle[ lowercaseName ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n} );\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button)$/i,\n\trclickable = /^(?:a|area)$/i;\n\njQuery.fn.extend( {\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\treturn ( elem[ name ] = value );\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\treturn elem[ name ];\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\t// Support: IE <=9 - 11 only\n\t\t\t\t// elem.tabIndex doesn't always return the\n\t\t\t\t// correct value when it hasn't been explicitly set\n\t\t\t\t// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\tif ( tabindex ) {\n\t\t\t\t\treturn parseInt( tabindex, 10 );\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\trfocusable.test( elem.nodeName ) ||\n\t\t\t\t\trclickable.test( elem.nodeName ) &&\n\t\t\t\t\telem.href\n\t\t\t\t) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t}\n} );\n\n// Support: IE <=11 only\n// Accessing the selectedIndex property\n// forces the browser to respect setting selected\n// on the option\n// The getter ensures a default option is selected\n// when in an optgroup\n// eslint rule \"no-unused-expressions\" is disabled for this code\n// since it considers such accessions noop\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tset: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\njQuery.each( [\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n} );\n\n\n\n\n\t// Strip and collapse whitespace according to HTML spec\n\t// https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace\n\tfunction stripAndCollapse( value ) {\n\t\tvar tokens = value.match( rnothtmlwhite ) || [];\n\t\treturn tokens.join( \" \" );\n\t}\n\n\nfunction getClass( elem ) {\n\treturn elem.getAttribute && elem.getAttribute( \"class\" ) || \"\";\n}\n\nfunction classesToArray( value ) {\n\tif ( Array.isArray( value ) ) {\n\t\treturn value;\n\t}\n\tif ( typeof value === \"string\" ) {\n\t\treturn value.match( rnothtmlwhite ) || [];\n\t}\n\treturn [];\n}\n\njQuery.fn.extend( {\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tclasses = classesToArray( value );\n\n\t\tif ( classes.length ) {\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( !arguments.length ) {\n\t\t\treturn this.attr( \"class\", \"\" );\n\t\t}\n\n\t\tclasses = classesToArray( value );\n\n\t\tif ( classes.length ) {\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) > -1 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisValidValue = type === \"string\" || Array.isArray( value );\n\n\t\tif ( typeof stateVal === \"boolean\" && isValidValue ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( isFunction( value ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).toggleClass(\n\t\t\t\t\tvalue.call( this, i, getClass( this ), stateVal ),\n\t\t\t\t\tstateVal\n\t\t\t\t);\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar className, i, self, classNames;\n\n\t\t\tif ( isValidValue ) {\n\n\t\t\t\t// Toggle individual class names\n\t\t\t\ti = 0;\n\t\t\t\tself = jQuery( this );\n\t\t\t\tclassNames = classesToArray( value );\n\n\t\t\t\twhile ( ( className = classNames[ i++ ] ) ) {\n\n\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( value === undefined || type === \"boolean\" ) {\n\t\t\t\tclassName = getClass( this );\n\t\t\t\tif ( className ) {\n\n\t\t\t\t\t// Store className if set\n\t\t\t\t\tdataPriv.set( this, \"__className__\", className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tif ( this.setAttribute ) {\n\t\t\t\t\tthis.setAttribute( \"class\",\n\t\t\t\t\t\tclassName || value === false ?\n\t\t\t\t\t\t\"\" :\n\t\t\t\t\t\tdataPriv.get( this, \"__className__\" ) || \"\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className, elem,\n\t\t\ti = 0;\n\n\t\tclassName = \" \" + selector + \" \";\n\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\tif ( elem.nodeType === 1 &&\n\t\t\t\t( \" \" + stripAndCollapse( getClass( elem ) ) + \" \" ).indexOf( className ) > -1 ) {\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n} );\n\n\n\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend( {\n\tval: function( value ) {\n\t\tvar hooks, ret, valueIsFunction,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] ||\n\t\t\t\t\tjQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks &&\n\t\t\t\t\t\"get\" in hooks &&\n\t\t\t\t\t( ret = hooks.get( elem, \"value\" ) ) !== undefined\n\t\t\t\t) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\t// Handle most common string cases\n\t\t\t\tif ( typeof ret === \"string\" ) {\n\t\t\t\t\treturn ret.replace( rreturn, \"\" );\n\t\t\t\t}\n\n\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\treturn ret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tvalueIsFunction = isFunction( value );\n\n\t\treturn this.each( function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( valueIsFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\n\t\t\t} else if ( Array.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !( \"set\" in hooks ) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\n\t\t\t\t\t// Support: IE <=10 - 11 only\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\t// Strip and collapse whitespace\n\t\t\t\t\t// https://html.spec.whatwg.org/#strip-and-collapse-whitespace\n\t\t\t\t\tstripAndCollapse( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option, i,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\",\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length;\n\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\ti = max;\n\n\t\t\t\t} else {\n\t\t\t\t\ti = one ? index : 0;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t// IE8-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t!option.disabled &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled ||\n\t\t\t\t\t\t\t\t!nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t/* eslint-disable no-cond-assign */\n\n\t\t\t\t\tif ( option.selected =\n\t\t\t\t\t\tjQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1\n\t\t\t\t\t) {\n\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* eslint-enable no-cond-assign */\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Radios and checkboxes getter/setter\njQuery.each( [ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( Array.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\treturn elem.getAttribute( \"value\" ) === null ? \"on\" : elem.value;\n\t\t};\n\t}\n} );\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\nsupport.focusin = \"onfocusin\" in window;\n\n\nvar rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\tstopPropagationCallback = function( e ) {\n\t\te.stopPropagation();\n\t};\n\njQuery.extend( jQuery.event, {\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special, lastElement,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split( \".\" ) : [];\n\n\t\tcur = lastElement = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) > -1 ) {\n\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split( \".\" );\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf( \":\" ) < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.rnamespace = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === ( elem.ownerDocument || document ) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tlastElement = cur;\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( dataPriv.get( cur, \"events\" ) || {} )[ event.type ] &&\n\t\t\t\tdataPriv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( ( !special._default ||\n\t\t\t\tspecial._default.apply( eventPath.pop(), data ) === false ) &&\n\t\t\t\tacceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name as the event.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\n\t\t\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\t\t\tlastElement.addEventListener( type, stopPropagationCallback );\n\t\t\t\t\t}\n\n\t\t\t\t\telem[ type ]();\n\n\t\t\t\t\tif ( event.isPropagationStopped() ) {\n\t\t\t\t\t\tlastElement.removeEventListener( type, stopPropagationCallback );\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Piggyback on a donor event to simulate a different one\n\t// Used only for `focus(in | out)` events\n\tsimulate: function( type, elem, event ) {\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true\n\t\t\t}\n\t\t);\n\n\t\tjQuery.event.trigger( e, null, elem );\n\t}\n\n} );\n\njQuery.fn.extend( {\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t} );\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[ 0 ];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n} );\n\n\n// Support: Firefox <=44\n// Firefox doesn't have focus(in | out) events\n// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787\n//\n// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1\n// focus(in | out) events fire after focus & blur events,\n// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order\n// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857\nif ( !support.focusin ) {\n\tjQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );\n\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tdataPriv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tdataPriv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdataPriv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t} );\n}\n\n\nvar\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( Array.isArray( obj ) ) {\n\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams(\n\t\t\t\t\tprefix + \"[\" + ( typeof v === \"object\" && v != null ? i : \"\" ) + \"]\",\n\t\t\t\t\tv,\n\t\t\t\t\ttraditional,\n\t\t\t\t\tadd\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\n\t} else if ( !traditional && toType( obj ) === \"object\" ) {\n\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, valueOrFunction ) {\n\n\t\t\t// If value is a function, invoke it and use its return value\n\t\t\tvar value = isFunction( valueOrFunction ) ?\n\t\t\t\tvalueOrFunction() :\n\t\t\t\tvalueOrFunction;\n\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( value == null ? \"\" : value );\n\t\t};\n\n\tif ( a == null ) {\n\t\treturn \"\";\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t} );\n\n\t} else {\n\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" );\n};\n\njQuery.fn.extend( {\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map( function() {\n\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t} )\n\t\t.filter( function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t} )\n\t\t.map( function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\tif ( val == null ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif ( Array.isArray( val ) ) {\n\t\t\t\treturn jQuery.map( val, function( val ) {\n\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t} ).get();\n\t}\n} );\n\n\njQuery.fn.extend( {\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( this[ 0 ] ) {\n\t\t\tif ( isFunction( html ) ) {\n\t\t\t\thtml = html.call( this[ 0 ] );\n\t\t\t}\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map( function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t} ).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( isFunction( html ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call( this, i ) );\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t} );\n\t},\n\n\twrap: function( html ) {\n\t\tvar htmlIsFunction = isFunction( html );\n\n\t\treturn this.each( function( i ) {\n\t\t\tjQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html );\n\t\t} );\n\t},\n\n\tunwrap: function( selector ) {\n\t\tthis.parent( selector ).not( \"body\" ).each( function() {\n\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t} );\n\t\treturn this;\n\t}\n} );\n\n\njQuery.expr.pseudos.hidden = function( elem ) {\n\treturn !jQuery.expr.pseudos.visible( elem );\n};\njQuery.expr.pseudos.visible = function( elem ) {\n\treturn !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );\n};\n\n\n\n\n// Support: Safari 8 only\n// In Safari 8 documents created via document.implementation.createHTMLDocument\n// collapse sibling forms: the second one becomes a child of the first one.\n// Because of that, this security measure has to be disabled in Safari 8.\n// https://bugs.webkit.org/show_bug.cgi?id=137337\nsupport.createHTMLDocument = ( function() {\n\tvar body = document.implementation.createHTMLDocument( \"\" ).body;\n\tbody.innerHTML = \"<form></form><form></form>\";\n\treturn body.childNodes.length === 2;\n} )();\n\n\n// Argument \"data\" should be string of html\n// context (optional): If specified, the fragment will be created in this context,\n// defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( typeof data !== \"string\" ) {\n\t\treturn [];\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\n\tvar base, parsed, scripts;\n\n\tif ( !context ) {\n\n\t\t// Stop scripts or inline event handlers from being executed immediately\n\t\t// by using document.implementation\n\t\tif ( support.createHTMLDocument ) {\n\t\t\tcontext = document.implementation.createHTMLDocument( \"\" );\n\n\t\t\t// Set the base href for the created document\n\t\t\t// so any parsed elements with URLs\n\t\t\t// are based on the document's URL (gh-2965)\n\t\t\tbase = context.createElement( \"base\" );\n\t\t\tbase.href = document.location.href;\n\t\t\tcontext.head.appendChild( base );\n\t\t} else {\n\t\t\tcontext = document;\n\t\t}\n\t}\n\n\tparsed = rsingleTag.exec( data );\n\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[ 1 ] ) ];\n\t}\n\n\tparsed = buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// Set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\t( curCSSTop + curCSSLeft ).indexOf( \"auto\" ) > -1;\n\n\t\t// Need to be able to calculate position if either\n\t\t// top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( isFunction( options ) ) {\n\n\t\t\t// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)\n\t\t\toptions = options.call( elem, i, jQuery.extend( {}, curOffset ) );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend( {\n\n\t// offset() relates an element's border box to the document origin\n\toffset: function( options ) {\n\n\t\t// Preserve chaining for setter\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each( function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t} );\n\t\t}\n\n\t\tvar rect, win,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !elem ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Return zeros for disconnected and hidden (display: none) elements (gh-2310)\n\t\t// Support: IE <=11 only\n\t\t// Running getBoundingClientRect on a\n\t\t// disconnected node in IE throws an error\n\t\tif ( !elem.getClientRects().length ) {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t\t// Get document-relative position by adding viewport scroll to viewport-relative gBCR\n\t\trect = elem.getBoundingClientRect();\n\t\twin = elem.ownerDocument.defaultView;\n\t\treturn {\n\t\t\ttop: rect.top + win.pageYOffset,\n\t\t\tleft: rect.left + win.pageXOffset\n\t\t};\n\t},\n\n\t// position() relates an element's margin box to its offset parent's padding box\n\t// This corresponds to the behavior of CSS absolute positioning\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset, doc,\n\t\t\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// position:fixed elements are offset from the viewport, which itself always has zero offset\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\n\t\t\t// Assume position:fixed implies availability of getBoundingClientRect\n\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t} else {\n\t\t\toffset = this.offset();\n\n\t\t\t// Account for the *real* offset parent, which can be the document or its root element\n\t\t\t// when a statically positioned element is identified\n\t\t\tdoc = elem.ownerDocument;\n\t\t\toffsetParent = elem.offsetParent || doc.documentElement;\n\t\t\twhile ( offsetParent &&\n\t\t\t\t( offsetParent === doc.body || offsetParent === doc.documentElement ) &&\n\t\t\t\tjQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\n\t\t\t\toffsetParent = offsetParent.parentNode;\n\t\t\t}\n\t\t\tif ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {\n\n\t\t\t\t// Incorporate borders into its offset, since they are outside its content origin\n\t\t\t\tparentOffset = jQuery( offsetParent ).offset();\n\t\t\t\tparentOffset.top += jQuery.css( offsetParent, \"borderTopWidth\", true );\n\t\t\t\tparentOffset.left += jQuery.css( offsetParent, \"borderLeftWidth\", true );\n\t\t\t}\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\t// This method will return documentElement in the following cases:\n\t// 1) For the element inside the iframe without offsetParent, this method will return\n\t//    documentElement of the parent window\n\t// 2) For the hidden or detached element\n\t// 3) For body or html element, i.e. in case of the html node - it will return itself\n\t//\n\t// but those exceptions were never presented as a real life use-cases\n\t// and might be considered as more preferable results.\n\t//\n\t// This logic, however, is not guaranteed and can change at any point in the future\n\toffsetParent: function() {\n\t\treturn this.map( function() {\n\t\t\tvar offsetParent = this.offsetParent;\n\n\t\t\twhile ( offsetParent && jQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || documentElement;\n\t\t} );\n\t}\n} );\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\n\t\t\t// Coalesce documents and windows\n\t\t\tvar win;\n\t\t\tif ( isWindow( elem ) ) {\n\t\t\t\twin = elem;\n\t\t\t} else if ( elem.nodeType === 9 ) {\n\t\t\t\twin = elem.defaultView;\n\t\t\t}\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : win.pageXOffset,\n\t\t\t\t\ttop ? val : win.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length );\n\t};\n} );\n\n// Support: Safari <=7 - 9.1, Chrome <=37 - 49\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347\n// getComputedStyle returns percent when specified for top/left/bottom/right;\n// rather than make the css module depend on the offset module, just check for it here\njQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\n\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n} );\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name },\n\t\tfunction( defaultExtra, funcName ) {\n\n\t\t// Margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( isWindow( elem ) ) {\n\n\t\t\t\t\t// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)\n\t\t\t\t\treturn funcName.indexOf( \"outer\" ) === 0 ?\n\t\t\t\t\t\telem[ \"inner\" + name ] :\n\t\t\t\t\t\telem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable );\n\t\t};\n\t} );\n} );\n\n\njQuery.each( ( \"blur focus focusin focusout resize scroll click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup contextmenu\" ).split( \" \" ),\n\tfunction( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n} );\n\njQuery.fn.extend( {\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n} );\n\n\n\n\njQuery.fn.extend( {\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ?\n\t\t\tthis.off( selector, \"**\" ) :\n\t\t\tthis.off( types, selector || \"**\", fn );\n\t}\n} );\n\n// Bind a function to a context, optionally partially applying any\n// arguments.\n// jQuery.proxy is deprecated to promote standards (specifically Function#bind)\n// However, it is not slated for removal any time soon\njQuery.proxy = function( fn, context ) {\n\tvar tmp, args, proxy;\n\n\tif ( typeof context === \"string\" ) {\n\t\ttmp = fn[ context ];\n\t\tcontext = fn;\n\t\tfn = tmp;\n\t}\n\n\t// Quick check to determine if target is callable, in the spec\n\t// this throws a TypeError, but we will just return undefined.\n\tif ( !isFunction( fn ) ) {\n\t\treturn undefined;\n\t}\n\n\t// Simulated bind\n\targs = slice.call( arguments, 2 );\n\tproxy = function() {\n\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t};\n\n\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\treturn proxy;\n};\n\njQuery.holdReady = function( hold ) {\n\tif ( hold ) {\n\t\tjQuery.readyWait++;\n\t} else {\n\t\tjQuery.ready( true );\n\t}\n};\njQuery.isArray = Array.isArray;\njQuery.parseJSON = JSON.parse;\njQuery.nodeName = nodeName;\njQuery.isFunction = isFunction;\njQuery.isWindow = isWindow;\njQuery.camelCase = camelCase;\njQuery.type = toType;\n\njQuery.now = Date.now;\n\njQuery.isNumeric = function( obj ) {\n\n\t// As of jQuery 3.0, isNumeric is limited to\n\t// strings and numbers (primitives or objects)\n\t// that can be coerced to finite numbers (gh-2662)\n\tvar type = jQuery.type( obj );\n\treturn ( type === \"number\" || type === \"string\" ) &&\n\n\t\t// parseFloat NaNs numeric-cast false positives (\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t!isNaN( obj - parseFloat( obj ) );\n};\n\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t} );\n}\n\n\n\n\nvar\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in AMD\n// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( !noGlobal ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n} );\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Scripts/jquery.validate.js",
    "content": "/*!\r\n * jQuery Validation Plugin v1.17.0\r\n *\r\n * https://jqueryvalidation.org/\r\n *\r\n * Copyright (c) 2017 Jörn Zaefferer\r\n * Released under the MIT license\r\n */\r\n(function( factory ) {\r\n\tif ( typeof define === \"function\" && define.amd ) {\r\n\t\tdefine( [\"jquery\"], factory );\r\n\t} else if (typeof module === \"object\" && module.exports) {\r\n\t\tmodule.exports = factory( require( \"jquery\" ) );\r\n\t} else {\r\n\t\tfactory( jQuery );\r\n\t}\r\n}(function( $ ) {\r\n\r\n$.extend( $.fn, {\n\n\t// https://jqueryvalidation.org/validate/\n\tvalidate: function( options ) {\n\n\t\t// If nothing is selected, return nothing; can't chain anyway\n\t\tif ( !this.length ) {\n\t\t\tif ( options && options.debug && window.console ) {\n\t\t\t\tconsole.warn( \"Nothing selected, can't validate, returning nothing.\" );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if a validator for this form was already created\n\t\tvar validator = $.data( this[ 0 ], \"validator\" );\n\t\tif ( validator ) {\n\t\t\treturn validator;\n\t\t}\n\n\t\t// Add novalidate tag if HTML5.\n\t\tthis.attr( \"novalidate\", \"novalidate\" );\n\n\t\tvalidator = new $.validator( options, this[ 0 ] );\n\t\t$.data( this[ 0 ], \"validator\", validator );\n\n\t\tif ( validator.settings.onsubmit ) {\n\n\t\t\tthis.on( \"click.validate\", \":submit\", function( event ) {\n\n\t\t\t\t// Track the used submit button to properly handle scripted\n\t\t\t\t// submits later.\n\t\t\t\tvalidator.submitButton = event.currentTarget;\n\n\t\t\t\t// Allow suppressing validation by adding a cancel class to the submit button\n\t\t\t\tif ( $( this ).hasClass( \"cancel\" ) ) {\n\t\t\t\t\tvalidator.cancelSubmit = true;\n\t\t\t\t}\n\n\t\t\t\t// Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button\n\t\t\t\tif ( $( this ).attr( \"formnovalidate\" ) !== undefined ) {\n\t\t\t\t\tvalidator.cancelSubmit = true;\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// Validate the form on submit\n\t\t\tthis.on( \"submit.validate\", function( event ) {\n\t\t\t\tif ( validator.settings.debug ) {\n\n\t\t\t\t\t// Prevent form submit to be able to see console output\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t\tfunction handle() {\n\t\t\t\t\tvar hidden, result;\n\n\t\t\t\t\t// Insert a hidden input as a replacement for the missing submit button\n\t\t\t\t\t// The hidden input is inserted in two cases:\n\t\t\t\t\t//   - A user defined a `submitHandler`\n\t\t\t\t\t//   - There was a pending request due to `remote` method and `stopRequest()`\n\t\t\t\t\t//     was called to submit the form in case it's valid\n\t\t\t\t\tif ( validator.submitButton && ( validator.settings.submitHandler || validator.formSubmitted ) ) {\n\t\t\t\t\t\thidden = $( \"<input type='hidden'/>\" )\n\t\t\t\t\t\t\t.attr( \"name\", validator.submitButton.name )\n\t\t\t\t\t\t\t.val( $( validator.submitButton ).val() )\n\t\t\t\t\t\t\t.appendTo( validator.currentForm );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( validator.settings.submitHandler ) {\n\t\t\t\t\t\tresult = validator.settings.submitHandler.call( validator, validator.currentForm, event );\n\t\t\t\t\t\tif ( hidden ) {\n\n\t\t\t\t\t\t\t// And clean up afterwards; thanks to no-block-scope, hidden can be referenced\n\t\t\t\t\t\t\thidden.remove();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( result !== undefined ) {\n\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t// Prevent submit for invalid forms or custom submit handlers\n\t\t\t\tif ( validator.cancelSubmit ) {\n\t\t\t\t\tvalidator.cancelSubmit = false;\n\t\t\t\t\treturn handle();\n\t\t\t\t}\n\t\t\t\tif ( validator.form() ) {\n\t\t\t\t\tif ( validator.pendingRequest ) {\n\t\t\t\t\t\tvalidator.formSubmitted = true;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn handle();\n\t\t\t\t} else {\n\t\t\t\t\tvalidator.focusInvalid();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\treturn validator;\n\t},\n\n\t// https://jqueryvalidation.org/valid/\n\tvalid: function() {\n\t\tvar valid, validator, errorList;\n\n\t\tif ( $( this[ 0 ] ).is( \"form\" ) ) {\n\t\t\tvalid = this.validate().form();\n\t\t} else {\n\t\t\terrorList = [];\n\t\t\tvalid = true;\n\t\t\tvalidator = $( this[ 0 ].form ).validate();\n\t\t\tthis.each( function() {\n\t\t\t\tvalid = validator.element( this ) && valid;\n\t\t\t\tif ( !valid ) {\n\t\t\t\t\terrorList = errorList.concat( validator.errorList );\n\t\t\t\t}\n\t\t\t} );\n\t\t\tvalidator.errorList = errorList;\n\t\t}\n\t\treturn valid;\n\t},\n\n\t// https://jqueryvalidation.org/rules/\n\trules: function( command, argument ) {\n\t\tvar element = this[ 0 ],\n\t\t\tsettings, staticRules, existingRules, data, param, filtered;\n\n\t\t// If nothing is selected, return empty object; can't chain anyway\n\t\tif ( element == null ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !element.form && element.hasAttribute( \"contenteditable\" ) ) {\n\t\t\telement.form = this.closest( \"form\" )[ 0 ];\n\t\t\telement.name = this.attr( \"name\" );\n\t\t}\n\n\t\tif ( element.form == null ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( command ) {\n\t\t\tsettings = $.data( element.form, \"validator\" ).settings;\n\t\t\tstaticRules = settings.rules;\n\t\t\texistingRules = $.validator.staticRules( element );\n\t\t\tswitch ( command ) {\n\t\t\tcase \"add\":\n\t\t\t\t$.extend( existingRules, $.validator.normalizeRule( argument ) );\n\n\t\t\t\t// Remove messages from rules, but allow them to be set separately\n\t\t\t\tdelete existingRules.messages;\n\t\t\t\tstaticRules[ element.name ] = existingRules;\n\t\t\t\tif ( argument.messages ) {\n\t\t\t\t\tsettings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"remove\":\n\t\t\t\tif ( !argument ) {\n\t\t\t\t\tdelete staticRules[ element.name ];\n\t\t\t\t\treturn existingRules;\n\t\t\t\t}\n\t\t\t\tfiltered = {};\n\t\t\t\t$.each( argument.split( /\\s/ ), function( index, method ) {\n\t\t\t\t\tfiltered[ method ] = existingRules[ method ];\n\t\t\t\t\tdelete existingRules[ method ];\n\t\t\t\t} );\n\t\t\t\treturn filtered;\n\t\t\t}\n\t\t}\n\n\t\tdata = $.validator.normalizeRules(\n\t\t$.extend(\n\t\t\t{},\n\t\t\t$.validator.classRules( element ),\n\t\t\t$.validator.attributeRules( element ),\n\t\t\t$.validator.dataRules( element ),\n\t\t\t$.validator.staticRules( element )\n\t\t), element );\n\n\t\t// Make sure required is at front\n\t\tif ( data.required ) {\n\t\t\tparam = data.required;\n\t\t\tdelete data.required;\n\t\t\tdata = $.extend( { required: param }, data );\n\t\t}\n\n\t\t// Make sure remote is at back\n\t\tif ( data.remote ) {\n\t\t\tparam = data.remote;\n\t\t\tdelete data.remote;\n\t\t\tdata = $.extend( data, { remote: param } );\n\t\t}\n\n\t\treturn data;\n\t}\n} );\n\n// Custom selectors\n$.extend( $.expr.pseudos || $.expr[ \":\" ], {\t\t// '|| $.expr[ \":\" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support\n\n\t// https://jqueryvalidation.org/blank-selector/\n\tblank: function( a ) {\n\t\treturn !$.trim( \"\" + $( a ).val() );\n\t},\n\n\t// https://jqueryvalidation.org/filled-selector/\n\tfilled: function( a ) {\n\t\tvar val = $( a ).val();\n\t\treturn val !== null && !!$.trim( \"\" + val );\n\t},\n\n\t// https://jqueryvalidation.org/unchecked-selector/\n\tunchecked: function( a ) {\n\t\treturn !$( a ).prop( \"checked\" );\n\t}\n} );\n\n// Constructor for validator\n$.validator = function( options, form ) {\n\tthis.settings = $.extend( true, {}, $.validator.defaults, options );\n\tthis.currentForm = form;\n\tthis.init();\n};\n\n// https://jqueryvalidation.org/jQuery.validator.format/\n$.validator.format = function( source, params ) {\n\tif ( arguments.length === 1 ) {\n\t\treturn function() {\n\t\t\tvar args = $.makeArray( arguments );\n\t\t\targs.unshift( source );\n\t\t\treturn $.validator.format.apply( this, args );\n\t\t};\n\t}\n\tif ( params === undefined ) {\n\t\treturn source;\n\t}\n\tif ( arguments.length > 2 && params.constructor !== Array  ) {\n\t\tparams = $.makeArray( arguments ).slice( 1 );\n\t}\n\tif ( params.constructor !== Array ) {\n\t\tparams = [ params ];\n\t}\n\t$.each( params, function( i, n ) {\n\t\tsource = source.replace( new RegExp( \"\\\\{\" + i + \"\\\\}\", \"g\" ), function() {\n\t\t\treturn n;\n\t\t} );\n\t} );\n\treturn source;\n};\n\n$.extend( $.validator, {\n\n\tdefaults: {\n\t\tmessages: {},\n\t\tgroups: {},\n\t\trules: {},\n\t\terrorClass: \"error\",\n\t\tpendingClass: \"pending\",\n\t\tvalidClass: \"valid\",\n\t\terrorElement: \"label\",\n\t\tfocusCleanup: false,\n\t\tfocusInvalid: true,\n\t\terrorContainer: $( [] ),\n\t\terrorLabelContainer: $( [] ),\n\t\tonsubmit: true,\n\t\tignore: \":hidden\",\n\t\tignoreTitle: false,\n\t\tonfocusin: function( element ) {\n\t\t\tthis.lastActive = element;\n\n\t\t\t// Hide error label and remove error class on focus if enabled\n\t\t\tif ( this.settings.focusCleanup ) {\n\t\t\t\tif ( this.settings.unhighlight ) {\n\t\t\t\t\tthis.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );\n\t\t\t\t}\n\t\t\t\tthis.hideThese( this.errorsFor( element ) );\n\t\t\t}\n\t\t},\n\t\tonfocusout: function( element ) {\n\t\t\tif ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {\n\t\t\t\tthis.element( element );\n\t\t\t}\n\t\t},\n\t\tonkeyup: function( element, event ) {\n\n\t\t\t// Avoid revalidate the field when pressing one of the following keys\n\t\t\t// Shift       => 16\n\t\t\t// Ctrl        => 17\n\t\t\t// Alt         => 18\n\t\t\t// Caps lock   => 20\n\t\t\t// End         => 35\n\t\t\t// Home        => 36\n\t\t\t// Left arrow  => 37\n\t\t\t// Up arrow    => 38\n\t\t\t// Right arrow => 39\n\t\t\t// Down arrow  => 40\n\t\t\t// Insert      => 45\n\t\t\t// Num lock    => 144\n\t\t\t// AltGr key   => 225\n\t\t\tvar excludedKeys = [\n\t\t\t\t16, 17, 18, 20, 35, 36, 37,\n\t\t\t\t38, 39, 40, 45, 144, 225\n\t\t\t];\n\n\t\t\tif ( event.which === 9 && this.elementValue( element ) === \"\" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {\n\t\t\t\treturn;\n\t\t\t} else if ( element.name in this.submitted || element.name in this.invalid ) {\n\t\t\t\tthis.element( element );\n\t\t\t}\n\t\t},\n\t\tonclick: function( element ) {\n\n\t\t\t// Click on selects, radiobuttons and checkboxes\n\t\t\tif ( element.name in this.submitted ) {\n\t\t\t\tthis.element( element );\n\n\t\t\t// Or option elements, check parent select in that case\n\t\t\t} else if ( element.parentNode.name in this.submitted ) {\n\t\t\t\tthis.element( element.parentNode );\n\t\t\t}\n\t\t},\n\t\thighlight: function( element, errorClass, validClass ) {\n\t\t\tif ( element.type === \"radio\" ) {\n\t\t\t\tthis.findByName( element.name ).addClass( errorClass ).removeClass( validClass );\n\t\t\t} else {\n\t\t\t\t$( element ).addClass( errorClass ).removeClass( validClass );\n\t\t\t}\n\t\t},\n\t\tunhighlight: function( element, errorClass, validClass ) {\n\t\t\tif ( element.type === \"radio\" ) {\n\t\t\t\tthis.findByName( element.name ).removeClass( errorClass ).addClass( validClass );\n\t\t\t} else {\n\t\t\t\t$( element ).removeClass( errorClass ).addClass( validClass );\n\t\t\t}\n\t\t}\n\t},\n\n\t// https://jqueryvalidation.org/jQuery.validator.setDefaults/\n\tsetDefaults: function( settings ) {\n\t\t$.extend( $.validator.defaults, settings );\n\t},\n\n\tmessages: {\n\t\trequired: \"This field is required.\",\n\t\tremote: \"Please fix this field.\",\n\t\temail: \"Please enter a valid email address.\",\n\t\turl: \"Please enter a valid URL.\",\n\t\tdate: \"Please enter a valid date.\",\n\t\tdateISO: \"Please enter a valid date (ISO).\",\n\t\tnumber: \"Please enter a valid number.\",\n\t\tdigits: \"Please enter only digits.\",\n\t\tequalTo: \"Please enter the same value again.\",\n\t\tmaxlength: $.validator.format( \"Please enter no more than {0} characters.\" ),\n\t\tminlength: $.validator.format( \"Please enter at least {0} characters.\" ),\n\t\trangelength: $.validator.format( \"Please enter a value between {0} and {1} characters long.\" ),\n\t\trange: $.validator.format( \"Please enter a value between {0} and {1}.\" ),\n\t\tmax: $.validator.format( \"Please enter a value less than or equal to {0}.\" ),\n\t\tmin: $.validator.format( \"Please enter a value greater than or equal to {0}.\" ),\n\t\tstep: $.validator.format( \"Please enter a multiple of {0}.\" )\n\t},\n\n\tautoCreateRanges: false,\n\n\tprototype: {\n\n\t\tinit: function() {\n\t\t\tthis.labelContainer = $( this.settings.errorLabelContainer );\n\t\t\tthis.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );\n\t\t\tthis.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );\n\t\t\tthis.submitted = {};\n\t\t\tthis.valueCache = {};\n\t\t\tthis.pendingRequest = 0;\n\t\t\tthis.pending = {};\n\t\t\tthis.invalid = {};\n\t\t\tthis.reset();\n\n\t\t\tvar groups = ( this.groups = {} ),\n\t\t\t\trules;\n\t\t\t$.each( this.settings.groups, function( key, value ) {\n\t\t\t\tif ( typeof value === \"string\" ) {\n\t\t\t\t\tvalue = value.split( /\\s/ );\n\t\t\t\t}\n\t\t\t\t$.each( value, function( index, name ) {\n\t\t\t\t\tgroups[ name ] = key;\n\t\t\t\t} );\n\t\t\t} );\n\t\t\trules = this.settings.rules;\n\t\t\t$.each( rules, function( key, value ) {\n\t\t\t\trules[ key ] = $.validator.normalizeRule( value );\n\t\t\t} );\n\n\t\t\tfunction delegate( event ) {\n\n\t\t\t\t// Set form expando on contenteditable\n\t\t\t\tif ( !this.form && this.hasAttribute( \"contenteditable\" ) ) {\n\t\t\t\t\tthis.form = $( this ).closest( \"form\" )[ 0 ];\n\t\t\t\t\tthis.name = $( this ).attr( \"name\" );\n\t\t\t\t}\n\n\t\t\t\tvar validator = $.data( this.form, \"validator\" ),\n\t\t\t\t\teventType = \"on\" + event.type.replace( /^validate/, \"\" ),\n\t\t\t\t\tsettings = validator.settings;\n\t\t\t\tif ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) {\n\t\t\t\t\tsettings[ eventType ].call( validator, this, event );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$( this.currentForm )\n\t\t\t\t.on( \"focusin.validate focusout.validate keyup.validate\",\n\t\t\t\t\t\":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], \" +\n\t\t\t\t\t\"[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], \" +\n\t\t\t\t\t\"[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], \" +\n\t\t\t\t\t\"[type='radio'], [type='checkbox'], [contenteditable], [type='button']\", delegate )\n\n\t\t\t\t// Support: Chrome, oldIE\n\t\t\t\t// \"select\" is provided as event.target when clicking a option\n\t\t\t\t.on( \"click.validate\", \"select, option, [type='radio'], [type='checkbox']\", delegate );\n\n\t\t\tif ( this.settings.invalidHandler ) {\n\t\t\t\t$( this.currentForm ).on( \"invalid-form.validate\", this.settings.invalidHandler );\n\t\t\t}\n\t\t},\n\n\t\t// https://jqueryvalidation.org/Validator.form/\n\t\tform: function() {\n\t\t\tthis.checkForm();\n\t\t\t$.extend( this.submitted, this.errorMap );\n\t\t\tthis.invalid = $.extend( {}, this.errorMap );\n\t\t\tif ( !this.valid() ) {\n\t\t\t\t$( this.currentForm ).triggerHandler( \"invalid-form\", [ this ] );\n\t\t\t}\n\t\t\tthis.showErrors();\n\t\t\treturn this.valid();\n\t\t},\n\n\t\tcheckForm: function() {\n\t\t\tthis.prepareForm();\n\t\t\tfor ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {\n\t\t\t\tthis.check( elements[ i ] );\n\t\t\t}\n\t\t\treturn this.valid();\n\t\t},\n\n\t\t// https://jqueryvalidation.org/Validator.element/\n\t\telement: function( element ) {\n\t\t\tvar cleanElement = this.clean( element ),\n\t\t\t\tcheckElement = this.validationTargetFor( cleanElement ),\n\t\t\t\tv = this,\n\t\t\t\tresult = true,\n\t\t\t\trs, group;\n\n\t\t\tif ( checkElement === undefined ) {\n\t\t\t\tdelete this.invalid[ cleanElement.name ];\n\t\t\t} else {\n\t\t\t\tthis.prepareElement( checkElement );\n\t\t\t\tthis.currentElements = $( checkElement );\n\n\t\t\t\t// If this element is grouped, then validate all group elements already\n\t\t\t\t// containing a value\n\t\t\t\tgroup = this.groups[ checkElement.name ];\n\t\t\t\tif ( group ) {\n\t\t\t\t\t$.each( this.groups, function( name, testgroup ) {\n\t\t\t\t\t\tif ( testgroup === group && name !== checkElement.name ) {\n\t\t\t\t\t\t\tcleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) );\n\t\t\t\t\t\t\tif ( cleanElement && cleanElement.name in v.invalid ) {\n\t\t\t\t\t\t\t\tv.currentElements.push( cleanElement );\n\t\t\t\t\t\t\t\tresult = v.check( cleanElement ) && result;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\trs = this.check( checkElement ) !== false;\n\t\t\t\tresult = result && rs;\n\t\t\t\tif ( rs ) {\n\t\t\t\t\tthis.invalid[ checkElement.name ] = false;\n\t\t\t\t} else {\n\t\t\t\t\tthis.invalid[ checkElement.name ] = true;\n\t\t\t\t}\n\n\t\t\t\tif ( !this.numberOfInvalids() ) {\n\n\t\t\t\t\t// Hide error containers on last error\n\t\t\t\t\tthis.toHide = this.toHide.add( this.containers );\n\t\t\t\t}\n\t\t\t\tthis.showErrors();\n\n\t\t\t\t// Add aria-invalid status for screen readers\n\t\t\t\t$( element ).attr( \"aria-invalid\", !rs );\n\t\t\t}\n\n\t\t\treturn result;\n\t\t},\n\n\t\t// https://jqueryvalidation.org/Validator.showErrors/\n\t\tshowErrors: function( errors ) {\n\t\t\tif ( errors ) {\n\t\t\t\tvar validator = this;\n\n\t\t\t\t// Add items to error list and map\n\t\t\t\t$.extend( this.errorMap, errors );\n\t\t\t\tthis.errorList = $.map( this.errorMap, function( message, name ) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tmessage: message,\n\t\t\t\t\t\telement: validator.findByName( name )[ 0 ]\n\t\t\t\t\t};\n\t\t\t\t} );\n\n\t\t\t\t// Remove items from success list\n\t\t\t\tthis.successList = $.grep( this.successList, function( element ) {\n\t\t\t\t\treturn !( element.name in errors );\n\t\t\t\t} );\n\t\t\t}\n\t\t\tif ( this.settings.showErrors ) {\n\t\t\t\tthis.settings.showErrors.call( this, this.errorMap, this.errorList );\n\t\t\t} else {\n\t\t\t\tthis.defaultShowErrors();\n\t\t\t}\n\t\t},\n\n\t\t// https://jqueryvalidation.org/Validator.resetForm/\n\t\tresetForm: function() {\n\t\t\tif ( $.fn.resetForm ) {\n\t\t\t\t$( this.currentForm ).resetForm();\n\t\t\t}\n\t\t\tthis.invalid = {};\n\t\t\tthis.submitted = {};\n\t\t\tthis.prepareForm();\n\t\t\tthis.hideErrors();\n\t\t\tvar elements = this.elements()\n\t\t\t\t.removeData( \"previousValue\" )\n\t\t\t\t.removeAttr( \"aria-invalid\" );\n\n\t\t\tthis.resetElements( elements );\n\t\t},\n\n\t\tresetElements: function( elements ) {\n\t\t\tvar i;\n\n\t\t\tif ( this.settings.unhighlight ) {\n\t\t\t\tfor ( i = 0; elements[ i ]; i++ ) {\n\t\t\t\t\tthis.settings.unhighlight.call( this, elements[ i ],\n\t\t\t\t\t\tthis.settings.errorClass, \"\" );\n\t\t\t\t\tthis.findByName( elements[ i ].name ).removeClass( this.settings.validClass );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\telements\n\t\t\t\t\t.removeClass( this.settings.errorClass )\n\t\t\t\t\t.removeClass( this.settings.validClass );\n\t\t\t}\n\t\t},\n\n\t\tnumberOfInvalids: function() {\n\t\t\treturn this.objectLength( this.invalid );\n\t\t},\n\n\t\tobjectLength: function( obj ) {\n\t\t\t/* jshint unused: false */\n\t\t\tvar count = 0,\n\t\t\t\ti;\n\t\t\tfor ( i in obj ) {\n\n\t\t\t\t// This check allows counting elements with empty error\n\t\t\t\t// message as invalid elements\n\t\t\t\tif ( obj[ i ] !== undefined && obj[ i ] !== null && obj[ i ] !== false ) {\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn count;\n\t\t},\n\n\t\thideErrors: function() {\n\t\t\tthis.hideThese( this.toHide );\n\t\t},\n\n\t\thideThese: function( errors ) {\n\t\t\terrors.not( this.containers ).text( \"\" );\n\t\t\tthis.addWrapper( errors ).hide();\n\t\t},\n\n\t\tvalid: function() {\n\t\t\treturn this.size() === 0;\n\t\t},\n\n\t\tsize: function() {\n\t\t\treturn this.errorList.length;\n\t\t},\n\n\t\tfocusInvalid: function() {\n\t\t\tif ( this.settings.focusInvalid ) {\n\t\t\t\ttry {\n\t\t\t\t\t$( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] )\n\t\t\t\t\t.filter( \":visible\" )\n\t\t\t\t\t.focus()\n\n\t\t\t\t\t// Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find\n\t\t\t\t\t.trigger( \"focusin\" );\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// Ignore IE throwing errors when focusing hidden elements\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tfindLastActive: function() {\n\t\t\tvar lastActive = this.lastActive;\n\t\t\treturn lastActive && $.grep( this.errorList, function( n ) {\n\t\t\t\treturn n.element.name === lastActive.name;\n\t\t\t} ).length === 1 && lastActive;\n\t\t},\n\n\t\telements: function() {\n\t\t\tvar validator = this,\n\t\t\t\trulesCache = {};\n\n\t\t\t// Select all valid inputs inside the form (no submit or reset buttons)\n\t\t\treturn $( this.currentForm )\n\t\t\t.find( \"input, select, textarea, [contenteditable]\" )\n\t\t\t.not( \":submit, :reset, :image, :disabled\" )\n\t\t\t.not( this.settings.ignore )\n\t\t\t.filter( function() {\n\t\t\t\tvar name = this.name || $( this ).attr( \"name\" ); // For contenteditable\n\t\t\t\tif ( !name && validator.settings.debug && window.console ) {\n\t\t\t\t\tconsole.error( \"%o has no name assigned\", this );\n\t\t\t\t}\n\n\t\t\t\t// Set form expando on contenteditable\n\t\t\t\tif ( this.hasAttribute( \"contenteditable\" ) ) {\n\t\t\t\t\tthis.form = $( this ).closest( \"form\" )[ 0 ];\n\t\t\t\t\tthis.name = name;\n\t\t\t\t}\n\n\t\t\t\t// Select only the first element for each name, and only those with rules specified\n\t\t\t\tif ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\trulesCache[ name ] = true;\n\t\t\t\treturn true;\n\t\t\t} );\n\t\t},\n\n\t\tclean: function( selector ) {\n\t\t\treturn $( selector )[ 0 ];\n\t\t},\n\n\t\terrors: function() {\n\t\t\tvar errorClass = this.settings.errorClass.split( \" \" ).join( \".\" );\n\t\t\treturn $( this.settings.errorElement + \".\" + errorClass, this.errorContext );\n\t\t},\n\n\t\tresetInternals: function() {\n\t\t\tthis.successList = [];\n\t\t\tthis.errorList = [];\n\t\t\tthis.errorMap = {};\n\t\t\tthis.toShow = $( [] );\n\t\t\tthis.toHide = $( [] );\n\t\t},\n\n\t\treset: function() {\n\t\t\tthis.resetInternals();\n\t\t\tthis.currentElements = $( [] );\n\t\t},\n\n\t\tprepareForm: function() {\n\t\t\tthis.reset();\n\t\t\tthis.toHide = this.errors().add( this.containers );\n\t\t},\n\n\t\tprepareElement: function( element ) {\n\t\t\tthis.reset();\n\t\t\tthis.toHide = this.errorsFor( element );\n\t\t},\n\n\t\telementValue: function( element ) {\n\t\t\tvar $element = $( element ),\n\t\t\t\ttype = element.type,\n\t\t\t\tval, idx;\n\n\t\t\tif ( type === \"radio\" || type === \"checkbox\" ) {\n\t\t\t\treturn this.findByName( element.name ).filter( \":checked\" ).val();\n\t\t\t} else if ( type === \"number\" && typeof element.validity !== \"undefined\" ) {\n\t\t\t\treturn element.validity.badInput ? \"NaN\" : $element.val();\n\t\t\t}\n\n\t\t\tif ( element.hasAttribute( \"contenteditable\" ) ) {\n\t\t\t\tval = $element.text();\n\t\t\t} else {\n\t\t\t\tval = $element.val();\n\t\t\t}\n\n\t\t\tif ( type === \"file\" ) {\n\n\t\t\t\t// Modern browser (chrome & safari)\n\t\t\t\tif ( val.substr( 0, 12 ) === \"C:\\\\fakepath\\\\\" ) {\n\t\t\t\t\treturn val.substr( 12 );\n\t\t\t\t}\n\n\t\t\t\t// Legacy browsers\n\t\t\t\t// Unix-based path\n\t\t\t\tidx = val.lastIndexOf( \"/\" );\n\t\t\t\tif ( idx >= 0 ) {\n\t\t\t\t\treturn val.substr( idx + 1 );\n\t\t\t\t}\n\n\t\t\t\t// Windows-based path\n\t\t\t\tidx = val.lastIndexOf( \"\\\\\" );\n\t\t\t\tif ( idx >= 0 ) {\n\t\t\t\t\treturn val.substr( idx + 1 );\n\t\t\t\t}\n\n\t\t\t\t// Just the file name\n\t\t\t\treturn val;\n\t\t\t}\n\n\t\t\tif ( typeof val === \"string\" ) {\n\t\t\t\treturn val.replace( /\\r/g, \"\" );\n\t\t\t}\n\t\t\treturn val;\n\t\t},\n\n\t\tcheck: function( element ) {\n\t\t\telement = this.validationTargetFor( this.clean( element ) );\n\n\t\t\tvar rules = $( element ).rules(),\n\t\t\t\trulesCount = $.map( rules, function( n, i ) {\n\t\t\t\t\treturn i;\n\t\t\t\t} ).length,\n\t\t\t\tdependencyMismatch = false,\n\t\t\t\tval = this.elementValue( element ),\n\t\t\t\tresult, method, rule, normalizer;\n\n\t\t\t// Prioritize the local normalizer defined for this element over the global one\n\t\t\t// if the former exists, otherwise user the global one in case it exists.\n\t\t\tif ( typeof rules.normalizer === \"function\" ) {\n\t\t\t\tnormalizer = rules.normalizer;\n\t\t\t} else if (\ttypeof this.settings.normalizer === \"function\" ) {\n\t\t\t\tnormalizer = this.settings.normalizer;\n\t\t\t}\n\n\t\t\t// If normalizer is defined, then call it to retreive the changed value instead\n\t\t\t// of using the real one.\n\t\t\t// Note that `this` in the normalizer is `element`.\n\t\t\tif ( normalizer ) {\n\t\t\t\tval = normalizer.call( element, val );\n\n\t\t\t\tif ( typeof val !== \"string\" ) {\n\t\t\t\t\tthrow new TypeError( \"The normalizer should return a string value.\" );\n\t\t\t\t}\n\n\t\t\t\t// Delete the normalizer from rules to avoid treating it as a pre-defined method.\n\t\t\t\tdelete rules.normalizer;\n\t\t\t}\n\n\t\t\tfor ( method in rules ) {\n\t\t\t\trule = { method: method, parameters: rules[ method ] };\n\t\t\t\ttry {\n\t\t\t\t\tresult = $.validator.methods[ method ].call( this, val, element, rule.parameters );\n\n\t\t\t\t\t// If a method indicates that the field is optional and therefore valid,\n\t\t\t\t\t// don't mark it as valid when there are no other rules\n\t\t\t\t\tif ( result === \"dependency-mismatch\" && rulesCount === 1 ) {\n\t\t\t\t\t\tdependencyMismatch = true;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tdependencyMismatch = false;\n\n\t\t\t\t\tif ( result === \"pending\" ) {\n\t\t\t\t\t\tthis.toHide = this.toHide.not( this.errorsFor( element ) );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !result ) {\n\t\t\t\t\t\tthis.formatAndAdd( element, rule );\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\tif ( this.settings.debug && window.console ) {\n\t\t\t\t\t\tconsole.log( \"Exception occurred when checking element \" + element.id + \", check the '\" + rule.method + \"' method.\", e );\n\t\t\t\t\t}\n\t\t\t\t\tif ( e instanceof TypeError ) {\n\t\t\t\t\t\te.message += \".  Exception occurred when checking element \" + element.id + \", check the '\" + rule.method + \"' method.\";\n\t\t\t\t\t}\n\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( dependencyMismatch ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( this.objectLength( rules ) ) {\n\t\t\t\tthis.successList.push( element );\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t// Return the custom message for the given element and validation method\n\t\t// specified in the element's HTML5 data attribute\n\t\t// return the generic message if present and no method specific message is present\n\t\tcustomDataMessage: function( element, method ) {\n\t\t\treturn $( element ).data( \"msg\" + method.charAt( 0 ).toUpperCase() +\n\t\t\t\tmethod.substring( 1 ).toLowerCase() ) || $( element ).data( \"msg\" );\n\t\t},\n\n\t\t// Return the custom message for the given element name and validation method\n\t\tcustomMessage: function( name, method ) {\n\t\t\tvar m = this.settings.messages[ name ];\n\t\t\treturn m && ( m.constructor === String ? m : m[ method ] );\n\t\t},\n\n\t\t// Return the first defined argument, allowing empty strings\n\t\tfindDefined: function() {\n\t\t\tfor ( var i = 0; i < arguments.length; i++ ) {\n\t\t\t\tif ( arguments[ i ] !== undefined ) {\n\t\t\t\t\treturn arguments[ i ];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\n\t\t// The second parameter 'rule' used to be a string, and extended to an object literal\n\t\t// of the following form:\n\t\t// rule = {\n\t\t//     method: \"method name\",\n\t\t//     parameters: \"the given method parameters\"\n\t\t// }\n\t\t//\n\t\t// The old behavior still supported, kept to maintain backward compatibility with\n\t\t// old code, and will be removed in the next major release.\n\t\tdefaultMessage: function( element, rule ) {\n\t\t\tif ( typeof rule === \"string\" ) {\n\t\t\t\trule = { method: rule };\n\t\t\t}\n\n\t\t\tvar message = this.findDefined(\n\t\t\t\t\tthis.customMessage( element.name, rule.method ),\n\t\t\t\t\tthis.customDataMessage( element, rule.method ),\n\n\t\t\t\t\t// 'title' is never undefined, so handle empty string as undefined\n\t\t\t\t\t!this.settings.ignoreTitle && element.title || undefined,\n\t\t\t\t\t$.validator.messages[ rule.method ],\n\t\t\t\t\t\"<strong>Warning: No message defined for \" + element.name + \"</strong>\"\n\t\t\t\t),\n\t\t\t\ttheregex = /\\$?\\{(\\d+)\\}/g;\n\t\t\tif ( typeof message === \"function\" ) {\n\t\t\t\tmessage = message.call( this, rule.parameters, element );\n\t\t\t} else if ( theregex.test( message ) ) {\n\t\t\t\tmessage = $.validator.format( message.replace( theregex, \"{$1}\" ), rule.parameters );\n\t\t\t}\n\n\t\t\treturn message;\n\t\t},\n\n\t\tformatAndAdd: function( element, rule ) {\n\t\t\tvar message = this.defaultMessage( element, rule );\n\n\t\t\tthis.errorList.push( {\n\t\t\t\tmessage: message,\n\t\t\t\telement: element,\n\t\t\t\tmethod: rule.method\n\t\t\t} );\n\n\t\t\tthis.errorMap[ element.name ] = message;\n\t\t\tthis.submitted[ element.name ] = message;\n\t\t},\n\n\t\taddWrapper: function( toToggle ) {\n\t\t\tif ( this.settings.wrapper ) {\n\t\t\t\ttoToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );\n\t\t\t}\n\t\t\treturn toToggle;\n\t\t},\n\n\t\tdefaultShowErrors: function() {\n\t\t\tvar i, elements, error;\n\t\t\tfor ( i = 0; this.errorList[ i ]; i++ ) {\n\t\t\t\terror = this.errorList[ i ];\n\t\t\t\tif ( this.settings.highlight ) {\n\t\t\t\t\tthis.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );\n\t\t\t\t}\n\t\t\t\tthis.showLabel( error.element, error.message );\n\t\t\t}\n\t\t\tif ( this.errorList.length ) {\n\t\t\t\tthis.toShow = this.toShow.add( this.containers );\n\t\t\t}\n\t\t\tif ( this.settings.success ) {\n\t\t\t\tfor ( i = 0; this.successList[ i ]; i++ ) {\n\t\t\t\t\tthis.showLabel( this.successList[ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( this.settings.unhighlight ) {\n\t\t\t\tfor ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {\n\t\t\t\t\tthis.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.toHide = this.toHide.not( this.toShow );\n\t\t\tthis.hideErrors();\n\t\t\tthis.addWrapper( this.toShow ).show();\n\t\t},\n\n\t\tvalidElements: function() {\n\t\t\treturn this.currentElements.not( this.invalidElements() );\n\t\t},\n\n\t\tinvalidElements: function() {\n\t\t\treturn $( this.errorList ).map( function() {\n\t\t\t\treturn this.element;\n\t\t\t} );\n\t\t},\n\n\t\tshowLabel: function( element, message ) {\n\t\t\tvar place, group, errorID, v,\n\t\t\t\terror = this.errorsFor( element ),\n\t\t\t\telementID = this.idOrName( element ),\n\t\t\t\tdescribedBy = $( element ).attr( \"aria-describedby\" );\n\n\t\t\tif ( error.length ) {\n\n\t\t\t\t// Refresh error/success class\n\t\t\t\terror.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );\n\n\t\t\t\t// Replace message on existing label\n\t\t\t\terror.html( message );\n\t\t\t} else {\n\n\t\t\t\t// Create error element\n\t\t\t\terror = $( \"<\" + this.settings.errorElement + \">\" )\n\t\t\t\t\t.attr( \"id\", elementID + \"-error\" )\n\t\t\t\t\t.addClass( this.settings.errorClass )\n\t\t\t\t\t.html( message || \"\" );\n\n\t\t\t\t// Maintain reference to the element to be placed into the DOM\n\t\t\t\tplace = error;\n\t\t\t\tif ( this.settings.wrapper ) {\n\n\t\t\t\t\t// Make sure the element is visible, even in IE\n\t\t\t\t\t// actually showing the wrapped element is handled elsewhere\n\t\t\t\t\tplace = error.hide().show().wrap( \"<\" + this.settings.wrapper + \"/>\" ).parent();\n\t\t\t\t}\n\t\t\t\tif ( this.labelContainer.length ) {\n\t\t\t\t\tthis.labelContainer.append( place );\n\t\t\t\t} else if ( this.settings.errorPlacement ) {\n\t\t\t\t\tthis.settings.errorPlacement.call( this, place, $( element ) );\n\t\t\t\t} else {\n\t\t\t\t\tplace.insertAfter( element );\n\t\t\t\t}\n\n\t\t\t\t// Link error back to the element\n\t\t\t\tif ( error.is( \"label\" ) ) {\n\n\t\t\t\t\t// If the error is a label, then associate using 'for'\n\t\t\t\t\terror.attr( \"for\", elementID );\n\n\t\t\t\t\t// If the element is not a child of an associated label, then it's necessary\n\t\t\t\t\t// to explicitly apply aria-describedby\n\t\t\t\t} else if ( error.parents( \"label[for='\" + this.escapeCssMeta( elementID ) + \"']\" ).length === 0 ) {\n\t\t\t\t\terrorID = error.attr( \"id\" );\n\n\t\t\t\t\t// Respect existing non-error aria-describedby\n\t\t\t\t\tif ( !describedBy ) {\n\t\t\t\t\t\tdescribedBy = errorID;\n\t\t\t\t\t} else if ( !describedBy.match( new RegExp( \"\\\\b\" + this.escapeCssMeta( errorID ) + \"\\\\b\" ) ) ) {\n\n\t\t\t\t\t\t// Add to end of list if not already present\n\t\t\t\t\t\tdescribedBy += \" \" + errorID;\n\t\t\t\t\t}\n\t\t\t\t\t$( element ).attr( \"aria-describedby\", describedBy );\n\n\t\t\t\t\t// If this element is grouped, then assign to all elements in the same group\n\t\t\t\t\tgroup = this.groups[ element.name ];\n\t\t\t\t\tif ( group ) {\n\t\t\t\t\t\tv = this;\n\t\t\t\t\t\t$.each( v.groups, function( name, testgroup ) {\n\t\t\t\t\t\t\tif ( testgroup === group ) {\n\t\t\t\t\t\t\t\t$( \"[name='\" + v.escapeCssMeta( name ) + \"']\", v.currentForm )\n\t\t\t\t\t\t\t\t\t.attr( \"aria-describedby\", error.attr( \"id\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !message && this.settings.success ) {\n\t\t\t\terror.text( \"\" );\n\t\t\t\tif ( typeof this.settings.success === \"string\" ) {\n\t\t\t\t\terror.addClass( this.settings.success );\n\t\t\t\t} else {\n\t\t\t\t\tthis.settings.success( error, element );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.toShow = this.toShow.add( error );\n\t\t},\n\n\t\terrorsFor: function( element ) {\n\t\t\tvar name = this.escapeCssMeta( this.idOrName( element ) ),\n\t\t\t\tdescriber = $( element ).attr( \"aria-describedby\" ),\n\t\t\t\tselector = \"label[for='\" + name + \"'], label[for='\" + name + \"'] *\";\n\n\t\t\t// 'aria-describedby' should directly reference the error element\n\t\t\tif ( describer ) {\n\t\t\t\tselector = selector + \", #\" + this.escapeCssMeta( describer )\n\t\t\t\t\t.replace( /\\s+/g, \", #\" );\n\t\t\t}\n\n\t\t\treturn this\n\t\t\t\t.errors()\n\t\t\t\t.filter( selector );\n\t\t},\n\n\t\t// See https://api.jquery.com/category/selectors/, for CSS\n\t\t// meta-characters that should be escaped in order to be used with JQuery\n\t\t// as a literal part of a name/id or any selector.\n\t\tescapeCssMeta: function( string ) {\n\t\t\treturn string.replace( /([\\\\!\"#$%&'()*+,./:;<=>?@\\[\\]^`{|}~])/g, \"\\\\$1\" );\n\t\t},\n\n\t\tidOrName: function( element ) {\n\t\t\treturn this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );\n\t\t},\n\n\t\tvalidationTargetFor: function( element ) {\n\n\t\t\t// If radio/checkbox, validate first element in group instead\n\t\t\tif ( this.checkable( element ) ) {\n\t\t\t\telement = this.findByName( element.name );\n\t\t\t}\n\n\t\t\t// Always apply ignore filter\n\t\t\treturn $( element ).not( this.settings.ignore )[ 0 ];\n\t\t},\n\n\t\tcheckable: function( element ) {\n\t\t\treturn ( /radio|checkbox/i ).test( element.type );\n\t\t},\n\n\t\tfindByName: function( name ) {\n\t\t\treturn $( this.currentForm ).find( \"[name='\" + this.escapeCssMeta( name ) + \"']\" );\n\t\t},\n\n\t\tgetLength: function( value, element ) {\n\t\t\tswitch ( element.nodeName.toLowerCase() ) {\n\t\t\tcase \"select\":\n\t\t\t\treturn $( \"option:selected\", element ).length;\n\t\t\tcase \"input\":\n\t\t\t\tif ( this.checkable( element ) ) {\n\t\t\t\t\treturn this.findByName( element.name ).filter( \":checked\" ).length;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn value.length;\n\t\t},\n\n\t\tdepend: function( param, element ) {\n\t\t\treturn this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ]( param, element ) : true;\n\t\t},\n\n\t\tdependTypes: {\n\t\t\t\"boolean\": function( param ) {\n\t\t\t\treturn param;\n\t\t\t},\n\t\t\t\"string\": function( param, element ) {\n\t\t\t\treturn !!$( param, element.form ).length;\n\t\t\t},\n\t\t\t\"function\": function( param, element ) {\n\t\t\t\treturn param( element );\n\t\t\t}\n\t\t},\n\n\t\toptional: function( element ) {\n\t\t\tvar val = this.elementValue( element );\n\t\t\treturn !$.validator.methods.required.call( this, val, element ) && \"dependency-mismatch\";\n\t\t},\n\n\t\tstartRequest: function( element ) {\n\t\t\tif ( !this.pending[ element.name ] ) {\n\t\t\t\tthis.pendingRequest++;\n\t\t\t\t$( element ).addClass( this.settings.pendingClass );\n\t\t\t\tthis.pending[ element.name ] = true;\n\t\t\t}\n\t\t},\n\n\t\tstopRequest: function( element, valid ) {\n\t\t\tthis.pendingRequest--;\n\n\t\t\t// Sometimes synchronization fails, make sure pendingRequest is never < 0\n\t\t\tif ( this.pendingRequest < 0 ) {\n\t\t\t\tthis.pendingRequest = 0;\n\t\t\t}\n\t\t\tdelete this.pending[ element.name ];\n\t\t\t$( element ).removeClass( this.settings.pendingClass );\n\t\t\tif ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {\n\t\t\t\t$( this.currentForm ).submit();\n\n\t\t\t\t// Remove the hidden input that was used as a replacement for the\n\t\t\t\t// missing submit button. The hidden input is added by `handle()`\n\t\t\t\t// to ensure that the value of the used submit button is passed on\n\t\t\t\t// for scripted submits triggered by this method\n\t\t\t\tif ( this.submitButton ) {\n\t\t\t\t\t$( \"input:hidden[name='\" + this.submitButton.name + \"']\", this.currentForm ).remove();\n\t\t\t\t}\n\n\t\t\t\tthis.formSubmitted = false;\n\t\t\t} else if ( !valid && this.pendingRequest === 0 && this.formSubmitted ) {\n\t\t\t\t$( this.currentForm ).triggerHandler( \"invalid-form\", [ this ] );\n\t\t\t\tthis.formSubmitted = false;\n\t\t\t}\n\t\t},\n\n\t\tpreviousValue: function( element, method ) {\n\t\t\tmethod = typeof method === \"string\" && method || \"remote\";\n\n\t\t\treturn $.data( element, \"previousValue\" ) || $.data( element, \"previousValue\", {\n\t\t\t\told: null,\n\t\t\t\tvalid: true,\n\t\t\t\tmessage: this.defaultMessage( element, { method: method } )\n\t\t\t} );\n\t\t},\n\n\t\t// Cleans up all forms and elements, removes validator-specific events\n\t\tdestroy: function() {\n\t\t\tthis.resetForm();\n\n\t\t\t$( this.currentForm )\n\t\t\t\t.off( \".validate\" )\n\t\t\t\t.removeData( \"validator\" )\n\t\t\t\t.find( \".validate-equalTo-blur\" )\n\t\t\t\t\t.off( \".validate-equalTo\" )\n\t\t\t\t\t.removeClass( \"validate-equalTo-blur\" );\n\t\t}\n\n\t},\n\n\tclassRuleSettings: {\n\t\trequired: { required: true },\n\t\temail: { email: true },\n\t\turl: { url: true },\n\t\tdate: { date: true },\n\t\tdateISO: { dateISO: true },\n\t\tnumber: { number: true },\n\t\tdigits: { digits: true },\n\t\tcreditcard: { creditcard: true }\n\t},\n\n\taddClassRules: function( className, rules ) {\n\t\tif ( className.constructor === String ) {\n\t\t\tthis.classRuleSettings[ className ] = rules;\n\t\t} else {\n\t\t\t$.extend( this.classRuleSettings, className );\n\t\t}\n\t},\n\n\tclassRules: function( element ) {\n\t\tvar rules = {},\n\t\t\tclasses = $( element ).attr( \"class\" );\n\n\t\tif ( classes ) {\n\t\t\t$.each( classes.split( \" \" ), function() {\n\t\t\t\tif ( this in $.validator.classRuleSettings ) {\n\t\t\t\t\t$.extend( rules, $.validator.classRuleSettings[ this ] );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t\treturn rules;\n\t},\n\n\tnormalizeAttributeRule: function( rules, type, method, value ) {\n\n\t\t// Convert the value to a number for number inputs, and for text for backwards compability\n\t\t// allows type=\"date\" and others to be compared as strings\n\t\tif ( /min|max|step/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {\n\t\t\tvalue = Number( value );\n\n\t\t\t// Support Opera Mini, which returns NaN for undefined minlength\n\t\t\tif ( isNaN( value ) ) {\n\t\t\t\tvalue = undefined;\n\t\t\t}\n\t\t}\n\n\t\tif ( value || value === 0 ) {\n\t\t\trules[ method ] = value;\n\t\t} else if ( type === method && type !== \"range\" ) {\n\n\t\t\t// Exception: the jquery validate 'range' method\n\t\t\t// does not test for the html5 'range' type\n\t\t\trules[ method ] = true;\n\t\t}\n\t},\n\n\tattributeRules: function( element ) {\n\t\tvar rules = {},\n\t\t\t$element = $( element ),\n\t\t\ttype = element.getAttribute( \"type\" ),\n\t\t\tmethod, value;\n\n\t\tfor ( method in $.validator.methods ) {\n\n\t\t\t// Support for <input required> in both html5 and older browsers\n\t\t\tif ( method === \"required\" ) {\n\t\t\t\tvalue = element.getAttribute( method );\n\n\t\t\t\t// Some browsers return an empty string for the required attribute\n\t\t\t\t// and non-HTML5 browsers might have required=\"\" markup\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\tvalue = true;\n\t\t\t\t}\n\n\t\t\t\t// Force non-HTML5 browsers to return bool\n\t\t\t\tvalue = !!value;\n\t\t\t} else {\n\t\t\t\tvalue = $element.attr( method );\n\t\t\t}\n\n\t\t\tthis.normalizeAttributeRule( rules, type, method, value );\n\t\t}\n\n\t\t// 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs\n\t\tif ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {\n\t\t\tdelete rules.maxlength;\n\t\t}\n\n\t\treturn rules;\n\t},\n\n\tdataRules: function( element ) {\n\t\tvar rules = {},\n\t\t\t$element = $( element ),\n\t\t\ttype = element.getAttribute( \"type\" ),\n\t\t\tmethod, value;\n\n\t\tfor ( method in $.validator.methods ) {\n\t\t\tvalue = $element.data( \"rule\" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );\n\t\t\tthis.normalizeAttributeRule( rules, type, method, value );\n\t\t}\n\t\treturn rules;\n\t},\n\n\tstaticRules: function( element ) {\n\t\tvar rules = {},\n\t\t\tvalidator = $.data( element.form, \"validator\" );\n\n\t\tif ( validator.settings.rules ) {\n\t\t\trules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};\n\t\t}\n\t\treturn rules;\n\t},\n\n\tnormalizeRules: function( rules, element ) {\n\n\t\t// Handle dependency check\n\t\t$.each( rules, function( prop, val ) {\n\n\t\t\t// Ignore rule when param is explicitly false, eg. required:false\n\t\t\tif ( val === false ) {\n\t\t\t\tdelete rules[ prop ];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( val.param || val.depends ) {\n\t\t\t\tvar keepRule = true;\n\t\t\t\tswitch ( typeof val.depends ) {\n\t\t\t\tcase \"string\":\n\t\t\t\t\tkeepRule = !!$( val.depends, element.form ).length;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"function\":\n\t\t\t\t\tkeepRule = val.depends.call( element, element );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( keepRule ) {\n\t\t\t\t\trules[ prop ] = val.param !== undefined ? val.param : true;\n\t\t\t\t} else {\n\t\t\t\t\t$.data( element.form, \"validator\" ).resetElements( $( element ) );\n\t\t\t\t\tdelete rules[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\t// Evaluate parameters\n\t\t$.each( rules, function( rule, parameter ) {\n\t\t\trules[ rule ] = $.isFunction( parameter ) && rule !== \"normalizer\" ? parameter( element ) : parameter;\n\t\t} );\n\n\t\t// Clean number parameters\n\t\t$.each( [ \"minlength\", \"maxlength\" ], function() {\n\t\t\tif ( rules[ this ] ) {\n\t\t\t\trules[ this ] = Number( rules[ this ] );\n\t\t\t}\n\t\t} );\n\t\t$.each( [ \"rangelength\", \"range\" ], function() {\n\t\t\tvar parts;\n\t\t\tif ( rules[ this ] ) {\n\t\t\t\tif ( $.isArray( rules[ this ] ) ) {\n\t\t\t\t\trules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ];\n\t\t\t\t} else if ( typeof rules[ this ] === \"string\" ) {\n\t\t\t\t\tparts = rules[ this ].replace( /[\\[\\]]/g, \"\" ).split( /[\\s,]+/ );\n\t\t\t\t\trules[ this ] = [ Number( parts[ 0 ] ), Number( parts[ 1 ] ) ];\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\tif ( $.validator.autoCreateRanges ) {\n\n\t\t\t// Auto-create ranges\n\t\t\tif ( rules.min != null && rules.max != null ) {\n\t\t\t\trules.range = [ rules.min, rules.max ];\n\t\t\t\tdelete rules.min;\n\t\t\t\tdelete rules.max;\n\t\t\t}\n\t\t\tif ( rules.minlength != null && rules.maxlength != null ) {\n\t\t\t\trules.rangelength = [ rules.minlength, rules.maxlength ];\n\t\t\t\tdelete rules.minlength;\n\t\t\t\tdelete rules.maxlength;\n\t\t\t}\n\t\t}\n\n\t\treturn rules;\n\t},\n\n\t// Converts a simple string to a {string: true} rule, e.g., \"required\" to {required:true}\n\tnormalizeRule: function( data ) {\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tvar transformed = {};\n\t\t\t$.each( data.split( /\\s/ ), function() {\n\t\t\t\ttransformed[ this ] = true;\n\t\t\t} );\n\t\t\tdata = transformed;\n\t\t}\n\t\treturn data;\n\t},\n\n\t// https://jqueryvalidation.org/jQuery.validator.addMethod/\n\taddMethod: function( name, method, message ) {\n\t\t$.validator.methods[ name ] = method;\n\t\t$.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];\n\t\tif ( method.length < 3 ) {\n\t\t\t$.validator.addClassRules( name, $.validator.normalizeRule( name ) );\n\t\t}\n\t},\n\n\t// https://jqueryvalidation.org/jQuery.validator.methods/\n\tmethods: {\n\n\t\t// https://jqueryvalidation.org/required-method/\n\t\trequired: function( value, element, param ) {\n\n\t\t\t// Check if dependency is met\n\t\t\tif ( !this.depend( param, element ) ) {\n\t\t\t\treturn \"dependency-mismatch\";\n\t\t\t}\n\t\t\tif ( element.nodeName.toLowerCase() === \"select\" ) {\n\n\t\t\t\t// Could be an array for select-multiple or a string, both are fine this way\n\t\t\t\tvar val = $( element ).val();\n\t\t\t\treturn val && val.length > 0;\n\t\t\t}\n\t\t\tif ( this.checkable( element ) ) {\n\t\t\t\treturn this.getLength( value, element ) > 0;\n\t\t\t}\n\t\t\treturn value.length > 0;\n\t\t},\n\n\t\t// https://jqueryvalidation.org/email-method/\n\t\temail: function( value, element ) {\n\n\t\t\t// From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address\n\t\t\t// Retrieved 2014-01-14\n\t\t\t// If you have a problem with this implementation, report a bug against the above spec\n\t\t\t// Or use custom methods to implement your own email validation\n\t\t\treturn this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );\n\t\t},\n\n\t\t// https://jqueryvalidation.org/url-method/\n\t\turl: function( value, element ) {\n\n\t\t\t// Copyright (c) 2010-2013 Diego Perini, MIT licensed\n\t\t\t// https://gist.github.com/dperini/729294\n\t\t\t// see also https://mathiasbynens.be/demo/url-regex\n\t\t\t// modified to allow protocol-relative URLs\n\t\t\treturn this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\\/\\/)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})).?)(?::\\d{2,5})?(?:[/?#]\\S*)?$/i.test( value );\n\t\t},\n\n\t\t// https://jqueryvalidation.org/date-method/\n\t\tdate: function( value, element ) {\n\t\t\treturn this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );\n\t\t},\n\n\t\t// https://jqueryvalidation.org/dateISO-method/\n\t\tdateISO: function( value, element ) {\n\t\t\treturn this.optional( element ) || /^\\d{4}[\\/\\-](0?[1-9]|1[012])[\\/\\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );\n\t\t},\n\n\t\t// https://jqueryvalidation.org/number-method/\n\t\tnumber: function( value, element ) {\n\t\t\treturn this.optional( element ) || /^(?:-?\\d+|-?\\d{1,3}(?:,\\d{3})+)?(?:\\.\\d+)?$/.test( value );\n\t\t},\n\n\t\t// https://jqueryvalidation.org/digits-method/\n\t\tdigits: function( value, element ) {\n\t\t\treturn this.optional( element ) || /^\\d+$/.test( value );\n\t\t},\n\n\t\t// https://jqueryvalidation.org/minlength-method/\n\t\tminlength: function( value, element, param ) {\n\t\t\tvar length = $.isArray( value ) ? value.length : this.getLength( value, element );\n\t\t\treturn this.optional( element ) || length >= param;\n\t\t},\n\n\t\t// https://jqueryvalidation.org/maxlength-method/\n\t\tmaxlength: function( value, element, param ) {\n\t\t\tvar length = $.isArray( value ) ? value.length : this.getLength( value, element );\n\t\t\treturn this.optional( element ) || length <= param;\n\t\t},\n\n\t\t// https://jqueryvalidation.org/rangelength-method/\n\t\trangelength: function( value, element, param ) {\n\t\t\tvar length = $.isArray( value ) ? value.length : this.getLength( value, element );\n\t\t\treturn this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );\n\t\t},\n\n\t\t// https://jqueryvalidation.org/min-method/\n\t\tmin: function( value, element, param ) {\n\t\t\treturn this.optional( element ) || value >= param;\n\t\t},\n\n\t\t// https://jqueryvalidation.org/max-method/\n\t\tmax: function( value, element, param ) {\n\t\t\treturn this.optional( element ) || value <= param;\n\t\t},\n\n\t\t// https://jqueryvalidation.org/range-method/\n\t\trange: function( value, element, param ) {\n\t\t\treturn this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );\n\t\t},\n\n\t\t// https://jqueryvalidation.org/step-method/\n\t\tstep: function( value, element, param ) {\n\t\t\tvar type = $( element ).attr( \"type\" ),\n\t\t\t\terrorMessage = \"Step attribute on input type \" + type + \" is not supported.\",\n\t\t\t\tsupportedTypes = [ \"text\", \"number\", \"range\" ],\n\t\t\t\tre = new RegExp( \"\\\\b\" + type + \"\\\\b\" ),\n\t\t\t\tnotSupported = type && !re.test( supportedTypes.join() ),\n\t\t\t\tdecimalPlaces = function( num ) {\n\t\t\t\t\tvar match = ( \"\" + num ).match( /(?:\\.(\\d+))?$/ );\n\t\t\t\t\tif ( !match ) {\n\t\t\t\t\t\treturn 0;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Number of digits right of decimal point.\n\t\t\t\t\treturn match[ 1 ] ? match[ 1 ].length : 0;\n\t\t\t\t},\n\t\t\t\ttoInt = function( num ) {\n\t\t\t\t\treturn Math.round( num * Math.pow( 10, decimals ) );\n\t\t\t\t},\n\t\t\t\tvalid = true,\n\t\t\t\tdecimals;\n\n\t\t\t// Works only for text, number and range input types\n\t\t\t// TODO find a way to support input types date, datetime, datetime-local, month, time and week\n\t\t\tif ( notSupported ) {\n\t\t\t\tthrow new Error( errorMessage );\n\t\t\t}\n\n\t\t\tdecimals = decimalPlaces( param );\n\n\t\t\t// Value can't have too many decimals\n\t\t\tif ( decimalPlaces( value ) > decimals || toInt( value ) % toInt( param ) !== 0 ) {\n\t\t\t\tvalid = false;\n\t\t\t}\n\n\t\t\treturn this.optional( element ) || valid;\n\t\t},\n\n\t\t// https://jqueryvalidation.org/equalTo-method/\n\t\tequalTo: function( value, element, param ) {\n\n\t\t\t// Bind to the blur event of the target in order to revalidate whenever the target field is updated\n\t\t\tvar target = $( param );\n\t\t\tif ( this.settings.onfocusout && target.not( \".validate-equalTo-blur\" ).length ) {\n\t\t\t\ttarget.addClass( \"validate-equalTo-blur\" ).on( \"blur.validate-equalTo\", function() {\n\t\t\t\t\t$( element ).valid();\n\t\t\t\t} );\n\t\t\t}\n\t\t\treturn value === target.val();\n\t\t},\n\n\t\t// https://jqueryvalidation.org/remote-method/\n\t\tremote: function( value, element, param, method ) {\n\t\t\tif ( this.optional( element ) ) {\n\t\t\t\treturn \"dependency-mismatch\";\n\t\t\t}\n\n\t\t\tmethod = typeof method === \"string\" && method || \"remote\";\n\n\t\t\tvar previous = this.previousValue( element, method ),\n\t\t\t\tvalidator, data, optionDataString;\n\n\t\t\tif ( !this.settings.messages[ element.name ] ) {\n\t\t\t\tthis.settings.messages[ element.name ] = {};\n\t\t\t}\n\t\t\tprevious.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ];\n\t\t\tthis.settings.messages[ element.name ][ method ] = previous.message;\n\n\t\t\tparam = typeof param === \"string\" && { url: param } || param;\n\t\t\toptionDataString = $.param( $.extend( { data: value }, param.data ) );\n\t\t\tif ( previous.old === optionDataString ) {\n\t\t\t\treturn previous.valid;\n\t\t\t}\n\n\t\t\tprevious.old = optionDataString;\n\t\t\tvalidator = this;\n\t\t\tthis.startRequest( element );\n\t\t\tdata = {};\n\t\t\tdata[ element.name ] = value;\n\t\t\t$.ajax( $.extend( true, {\n\t\t\t\tmode: \"abort\",\n\t\t\t\tport: \"validate\" + element.name,\n\t\t\t\tdataType: \"json\",\n\t\t\t\tdata: data,\n\t\t\t\tcontext: validator.currentForm,\n\t\t\t\tsuccess: function( response ) {\n\t\t\t\t\tvar valid = response === true || response === \"true\",\n\t\t\t\t\t\terrors, message, submitted;\n\n\t\t\t\t\tvalidator.settings.messages[ element.name ][ method ] = previous.originalMessage;\n\t\t\t\t\tif ( valid ) {\n\t\t\t\t\t\tsubmitted = validator.formSubmitted;\n\t\t\t\t\t\tvalidator.resetInternals();\n\t\t\t\t\t\tvalidator.toHide = validator.errorsFor( element );\n\t\t\t\t\t\tvalidator.formSubmitted = submitted;\n\t\t\t\t\t\tvalidator.successList.push( element );\n\t\t\t\t\t\tvalidator.invalid[ element.name ] = false;\n\t\t\t\t\t\tvalidator.showErrors();\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors = {};\n\t\t\t\t\t\tmessage = response || validator.defaultMessage( element, { method: method, parameters: value } );\n\t\t\t\t\t\terrors[ element.name ] = previous.message = message;\n\t\t\t\t\t\tvalidator.invalid[ element.name ] = true;\n\t\t\t\t\t\tvalidator.showErrors( errors );\n\t\t\t\t\t}\n\t\t\t\t\tprevious.valid = valid;\n\t\t\t\t\tvalidator.stopRequest( element, valid );\n\t\t\t\t}\n\t\t\t}, param ) );\n\t\t\treturn \"pending\";\n\t\t}\n\t}\n\n} );\n\r\n// Ajax mode: abort\n// usage: $.ajax({ mode: \"abort\"[, port: \"uniqueport\"]});\n// if mode:\"abort\" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()\n\nvar pendingRequests = {},\n\tajax;\n\n// Use a prefilter if available (1.5+)\nif ( $.ajaxPrefilter ) {\n\t$.ajaxPrefilter( function( settings, _, xhr ) {\n\t\tvar port = settings.port;\n\t\tif ( settings.mode === \"abort\" ) {\n\t\t\tif ( pendingRequests[ port ] ) {\n\t\t\t\tpendingRequests[ port ].abort();\n\t\t\t}\n\t\t\tpendingRequests[ port ] = xhr;\n\t\t}\n\t} );\n} else {\n\n\t// Proxy ajax\n\tajax = $.ajax;\n\t$.ajax = function( settings ) {\n\t\tvar mode = ( \"mode\" in settings ? settings : $.ajaxSettings ).mode,\n\t\t\tport = ( \"port\" in settings ? settings : $.ajaxSettings ).port;\n\t\tif ( mode === \"abort\" ) {\n\t\t\tif ( pendingRequests[ port ] ) {\n\t\t\t\tpendingRequests[ port ].abort();\n\t\t\t}\n\t\t\tpendingRequests[ port ] = ajax.apply( this, arguments );\n\t\t\treturn pendingRequests[ port ];\n\t\t}\n\t\treturn ajax.apply( this, arguments );\n\t};\n}\nreturn $;\r\n}));"
  },
  {
    "path": "ad/NHA/files/wwwroot/Scripts/jquery.validate.unobtrusive.js",
    "content": "// Unobtrusive validation support library for jQuery and jQuery Validate\n// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n// @version v3.2.11\n\n/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */\n/*global document: false, jQuery: false */\n\n(function (factory) {\n    if (typeof define === 'function' && define.amd) {\n        // AMD. Register as an anonymous module.\n        define(\"jquery.validate.unobtrusive\", ['jquery-validation'], factory);\n    } else if (typeof module === 'object' && module.exports) {\n        // CommonJS-like environments that support module.exports     \n        module.exports = factory(require('jquery-validation'));\n    } else {\n        // Browser global\n        jQuery.validator.unobtrusive = factory(jQuery);\n    }\n}(function ($) {\n    var $jQval = $.validator,\n        adapters,\n        data_validation = \"unobtrusiveValidation\";\n\n    function setValidationValues(options, ruleName, value) {\n        options.rules[ruleName] = value;\n        if (options.message) {\n            options.messages[ruleName] = options.message;\n        }\n    }\n\n    function splitAndTrim(value) {\n        return value.replace(/^\\s+|\\s+$/g, \"\").split(/\\s*,\\s*/g);\n    }\n\n    function escapeAttributeValue(value) {\n        // As mentioned on http://api.jquery.com/category/selectors/\n        return value.replace(/([!\"#$%&'()*+,./:;<=>?@\\[\\\\\\]^`{|}~])/g, \"\\\\$1\");\n    }\n\n    function getModelPrefix(fieldName) {\n        return fieldName.substr(0, fieldName.lastIndexOf(\".\") + 1);\n    }\n\n    function appendModelPrefix(value, prefix) {\n        if (value.indexOf(\"*.\") === 0) {\n            value = value.replace(\"*.\", prefix);\n        }\n        return value;\n    }\n\n    function onError(error, inputElement) {  // 'this' is the form element\n        var container = $(this).find(\"[data-valmsg-for='\" + escapeAttributeValue(inputElement[0].name) + \"']\"),\n            replaceAttrValue = container.attr(\"data-valmsg-replace\"),\n            replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null;\n\n        container.removeClass(\"field-validation-valid\").addClass(\"field-validation-error\");\n        error.data(\"unobtrusiveContainer\", container);\n\n        if (replace) {\n            container.empty();\n            error.removeClass(\"input-validation-error\").appendTo(container);\n        }\n        else {\n            error.hide();\n        }\n    }\n\n    function onErrors(event, validator) {  // 'this' is the form element\n        var container = $(this).find(\"[data-valmsg-summary=true]\"),\n            list = container.find(\"ul\");\n\n        if (list && list.length && validator.errorList.length) {\n            list.empty();\n            container.addClass(\"validation-summary-errors\").removeClass(\"validation-summary-valid\");\n\n            $.each(validator.errorList, function () {\n                $(\"<li />\").html(this.message).appendTo(list);\n            });\n        }\n    }\n\n    function onSuccess(error) {  // 'this' is the form element\n        var container = error.data(\"unobtrusiveContainer\");\n\n        if (container) {\n            var replaceAttrValue = container.attr(\"data-valmsg-replace\"),\n                replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null;\n\n            container.addClass(\"field-validation-valid\").removeClass(\"field-validation-error\");\n            error.removeData(\"unobtrusiveContainer\");\n\n            if (replace) {\n                container.empty();\n            }\n        }\n    }\n\n    function onReset(event) {  // 'this' is the form element\n        var $form = $(this),\n            key = '__jquery_unobtrusive_validation_form_reset';\n        if ($form.data(key)) {\n            return;\n        }\n        // Set a flag that indicates we're currently resetting the form.\n        $form.data(key, true);\n        try {\n            $form.data(\"validator\").resetForm();\n        } finally {\n            $form.removeData(key);\n        }\n\n        $form.find(\".validation-summary-errors\")\n            .addClass(\"validation-summary-valid\")\n            .removeClass(\"validation-summary-errors\");\n        $form.find(\".field-validation-error\")\n            .addClass(\"field-validation-valid\")\n            .removeClass(\"field-validation-error\")\n            .removeData(\"unobtrusiveContainer\")\n            .find(\">*\")  // If we were using valmsg-replace, get the underlying error\n            .removeData(\"unobtrusiveContainer\");\n    }\n\n    function validationInfo(form) {\n        var $form = $(form),\n            result = $form.data(data_validation),\n            onResetProxy = $.proxy(onReset, form),\n            defaultOptions = $jQval.unobtrusive.options || {},\n            execInContext = function (name, args) {\n                var func = defaultOptions[name];\n                func && $.isFunction(func) && func.apply(form, args);\n            };\n\n        if (!result) {\n            result = {\n                options: {  // options structure passed to jQuery Validate's validate() method\n                    errorClass: defaultOptions.errorClass || \"input-validation-error\",\n                    errorElement: defaultOptions.errorElement || \"span\",\n                    errorPlacement: function () {\n                        onError.apply(form, arguments);\n                        execInContext(\"errorPlacement\", arguments);\n                    },\n                    invalidHandler: function () {\n                        onErrors.apply(form, arguments);\n                        execInContext(\"invalidHandler\", arguments);\n                    },\n                    messages: {},\n                    rules: {},\n                    success: function () {\n                        onSuccess.apply(form, arguments);\n                        execInContext(\"success\", arguments);\n                    }\n                },\n                attachValidation: function () {\n                    $form\n                        .off(\"reset.\" + data_validation, onResetProxy)\n                        .on(\"reset.\" + data_validation, onResetProxy)\n                        .validate(this.options);\n                },\n                validate: function () {  // a validation function that is called by unobtrusive Ajax\n                    $form.validate();\n                    return $form.valid();\n                }\n            };\n            $form.data(data_validation, result);\n        }\n\n        return result;\n    }\n\n    $jQval.unobtrusive = {\n        adapters: [],\n\n        parseElement: function (element, skipAttach) {\n            /// <summary>\n            /// Parses a single HTML element for unobtrusive validation attributes.\n            /// </summary>\n            /// <param name=\"element\" domElement=\"true\">The HTML element to be parsed.</param>\n            /// <param name=\"skipAttach\" type=\"Boolean\">[Optional] true to skip attaching the\n            /// validation to the form. If parsing just this single element, you should specify true.\n            /// If parsing several elements, you should specify false, and manually attach the validation\n            /// to the form when you are finished. The default is false.</param>\n            var $element = $(element),\n                form = $element.parents(\"form\")[0],\n                valInfo, rules, messages;\n\n            if (!form) {  // Cannot do client-side validation without a form\n                return;\n            }\n\n            valInfo = validationInfo(form);\n            valInfo.options.rules[element.name] = rules = {};\n            valInfo.options.messages[element.name] = messages = {};\n\n            $.each(this.adapters, function () {\n                var prefix = \"data-val-\" + this.name,\n                    message = $element.attr(prefix),\n                    paramValues = {};\n\n                if (message !== undefined) {  // Compare against undefined, because an empty message is legal (and falsy)\n                    prefix += \"-\";\n\n                    $.each(this.params, function () {\n                        paramValues[this] = $element.attr(prefix + this);\n                    });\n\n                    this.adapt({\n                        element: element,\n                        form: form,\n                        message: message,\n                        params: paramValues,\n                        rules: rules,\n                        messages: messages\n                    });\n                }\n            });\n\n            $.extend(rules, { \"__dummy__\": true });\n\n            if (!skipAttach) {\n                valInfo.attachValidation();\n            }\n        },\n\n        parse: function (selector) {\n            /// <summary>\n            /// Parses all the HTML elements in the specified selector. It looks for input elements decorated\n            /// with the [data-val=true] attribute value and enables validation according to the data-val-*\n            /// attribute values.\n            /// </summary>\n            /// <param name=\"selector\" type=\"String\">Any valid jQuery selector.</param>\n\n            // $forms includes all forms in selector's DOM hierarchy (parent, children and self) that have at least one\n            // element with data-val=true\n            var $selector = $(selector),\n                $forms = $selector.parents()\n                    .addBack()\n                    .filter(\"form\")\n                    .add($selector.find(\"form\"))\n                    .has(\"[data-val=true]\");\n\n            $selector.find(\"[data-val=true]\").each(function () {\n                $jQval.unobtrusive.parseElement(this, true);\n            });\n\n            $forms.each(function () {\n                var info = validationInfo(this);\n                if (info) {\n                    info.attachValidation();\n                }\n            });\n        }\n    };\n\n    adapters = $jQval.unobtrusive.adapters;\n\n    adapters.add = function (adapterName, params, fn) {\n        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation.</summary>\n        /// <param name=\"adapterName\" type=\"String\">The name of the adapter to be added. This matches the name used\n        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>\n        /// <param name=\"params\" type=\"Array\" optional=\"true\">[Optional] An array of parameter names (strings) that will\n        /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and\n        /// mmmm is the parameter name).</param>\n        /// <param name=\"fn\" type=\"Function\">The function to call, which adapts the values from the HTML\n        /// attributes into jQuery Validate rules and/or messages.</param>\n        /// <returns type=\"jQuery.validator.unobtrusive.adapters\" />\n        if (!fn) {  // Called with no params, just a function\n            fn = params;\n            params = [];\n        }\n        this.push({ name: adapterName, params: params, adapt: fn });\n        return this;\n    };\n\n    adapters.addBool = function (adapterName, ruleName) {\n        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where\n        /// the jQuery Validate validation rule has no parameter values.</summary>\n        /// <param name=\"adapterName\" type=\"String\">The name of the adapter to be added. This matches the name used\n        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>\n        /// <param name=\"ruleName\" type=\"String\" optional=\"true\">[Optional] The name of the jQuery Validate rule. If not provided, the value\n        /// of adapterName will be used instead.</param>\n        /// <returns type=\"jQuery.validator.unobtrusive.adapters\" />\n        return this.add(adapterName, function (options) {\n            setValidationValues(options, ruleName || adapterName, true);\n        });\n    };\n\n    adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) {\n        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where\n        /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and\n        /// one for min-and-max). The HTML parameters are expected to be named -min and -max.</summary>\n        /// <param name=\"adapterName\" type=\"String\">The name of the adapter to be added. This matches the name used\n        /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name).</param>\n        /// <param name=\"minRuleName\" type=\"String\">The name of the jQuery Validate rule to be used when you only\n        /// have a minimum value.</param>\n        /// <param name=\"maxRuleName\" type=\"String\">The name of the jQuery Validate rule to be used when you only\n        /// have a maximum value.</param>\n        /// <param name=\"minMaxRuleName\" type=\"String\">The name of the jQuery Validate rule to be used when you\n        /// have both a minimum and maximum value.</param>\n        /// <param name=\"minAttribute\" type=\"String\" optional=\"true\">[Optional] The name of the HTML attribute that\n        /// contains the minimum value. The default is \"min\".</param>\n        /// <param name=\"maxAttribute\" type=\"String\" optional=\"true\">[Optional] The name of the HTML attribute that\n        /// contains the maximum value. The default is \"max\".</param>\n        /// <returns type=\"jQuery.validator.unobtrusive.adapters\" />\n        return this.add(adapterName, [minAttribute || \"min\", maxAttribute || \"max\"], function (options) {\n            var min = options.params.min,\n                max = options.params.max;\n\n            if (min && max) {\n                setValidationValues(options, minMaxRuleName, [min, max]);\n            }\n            else if (min) {\n                setValidationValues(options, minRuleName, min);\n            }\n            else if (max) {\n                setValidationValues(options, maxRuleName, max);\n            }\n        });\n    };\n\n    adapters.addSingleVal = function (adapterName, attribute, ruleName) {\n        /// <summary>Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where\n        /// the jQuery Validate validation rule has a single value.</summary>\n        /// <param name=\"adapterName\" type=\"String\">The name of the adapter to be added. This matches the name used\n        /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name).</param>\n        /// <param name=\"attribute\" type=\"String\">[Optional] The name of the HTML attribute that contains the value.\n        /// The default is \"val\".</param>\n        /// <param name=\"ruleName\" type=\"String\" optional=\"true\">[Optional] The name of the jQuery Validate rule. If not provided, the value\n        /// of adapterName will be used instead.</param>\n        /// <returns type=\"jQuery.validator.unobtrusive.adapters\" />\n        return this.add(adapterName, [attribute || \"val\"], function (options) {\n            setValidationValues(options, ruleName || adapterName, options.params[attribute]);\n        });\n    };\n\n    $jQval.addMethod(\"__dummy__\", function (value, element, params) {\n        return true;\n    });\n\n    $jQval.addMethod(\"regex\", function (value, element, params) {\n        var match;\n        if (this.optional(element)) {\n            return true;\n        }\n\n        match = new RegExp(params).exec(value);\n        return (match && (match.index === 0) && (match[0].length === value.length));\n    });\n\n    $jQval.addMethod(\"nonalphamin\", function (value, element, nonalphamin) {\n        var match;\n        if (nonalphamin) {\n            match = value.match(/\\W/g);\n            match = match && match.length >= nonalphamin;\n        }\n        return match;\n    });\n\n    if ($jQval.methods.extension) {\n        adapters.addSingleVal(\"accept\", \"mimtype\");\n        adapters.addSingleVal(\"extension\", \"extension\");\n    } else {\n        // for backward compatibility, when the 'extension' validation method does not exist, such as with versions\n        // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for\n        // validating the extension, and ignore mime-type validations as they are not supported.\n        adapters.addSingleVal(\"extension\", \"extension\", \"accept\");\n    }\n\n    adapters.addSingleVal(\"regex\", \"pattern\");\n    adapters.addBool(\"creditcard\").addBool(\"date\").addBool(\"digits\").addBool(\"email\").addBool(\"number\").addBool(\"url\");\n    adapters.addMinMax(\"length\", \"minlength\", \"maxlength\", \"rangelength\").addMinMax(\"range\", \"min\", \"max\", \"range\");\n    adapters.addMinMax(\"minlength\", \"minlength\").addMinMax(\"maxlength\", \"minlength\", \"maxlength\");\n    adapters.add(\"equalto\", [\"other\"], function (options) {\n        var prefix = getModelPrefix(options.element.name),\n            other = options.params.other,\n            fullOtherName = appendModelPrefix(other, prefix),\n            element = $(options.form).find(\":input\").filter(\"[name='\" + escapeAttributeValue(fullOtherName) + \"']\")[0];\n\n        setValidationValues(options, \"equalTo\", element);\n    });\n    adapters.add(\"required\", function (options) {\n        // jQuery Validate equates \"required\" with \"mandatory\" for checkbox elements\n        if (options.element.tagName.toUpperCase() !== \"INPUT\" || options.element.type.toUpperCase() !== \"CHECKBOX\") {\n            setValidationValues(options, \"required\", true);\n        }\n    });\n    adapters.add(\"remote\", [\"url\", \"type\", \"additionalfields\"], function (options) {\n        var value = {\n            url: options.params.url,\n            type: options.params.type || \"GET\",\n            data: {}\n        },\n            prefix = getModelPrefix(options.element.name);\n\n        $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {\n            var paramName = appendModelPrefix(fieldName, prefix);\n            value.data[paramName] = function () {\n                var field = $(options.form).find(\":input\").filter(\"[name='\" + escapeAttributeValue(paramName) + \"']\");\n                // For checkboxes and radio buttons, only pick up values from checked fields.\n                if (field.is(\":checkbox\")) {\n                    return field.filter(\":checked\").val() || field.filter(\":hidden\").val() || '';\n                }\n                else if (field.is(\":radio\")) {\n                    return field.filter(\":checked\").val() || '';\n                }\n                return field.val();\n            };\n        });\n\n        setValidationValues(options, \"remote\", value);\n    });\n    adapters.add(\"password\", [\"min\", \"nonalphamin\", \"regex\"], function (options) {\n        if (options.params.min) {\n            setValidationValues(options, \"minlength\", options.params.min);\n        }\n        if (options.params.nonalphamin) {\n            setValidationValues(options, \"nonalphamin\", options.params.nonalphamin);\n        }\n        if (options.params.regex) {\n            setValidationValues(options, \"regex\", options.params.regex);\n        }\n    });\n    adapters.add(\"fileextensions\", [\"extensions\"], function (options) {\n        setValidationValues(options, \"extension\", options.params.extensions);\n    });\n\n    $(function () {\n        $jQval.unobtrusive.parse(document);\n    });\n\n    return $jQval.unobtrusive;\n}));\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Scripts/modernizr-2.8.3.js",
    "content": "/*!\n * Modernizr v2.8.3\n * www.modernizr.com\n *\n * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton\n * Available under the BSD and MIT licenses: www.modernizr.com/license/\n */\n\n/*\n * Modernizr tests which native CSS3 and HTML5 features are available in\n * the current UA and makes the results available to you in two ways:\n * as properties on a global Modernizr object, and as classes on the\n * <html> element. This information allows you to progressively enhance\n * your pages with a granular level of control over the experience.\n *\n * Modernizr has an optional (not included) conditional resource loader\n * called Modernizr.load(), based on Yepnope.js (yepnopejs.com).\n * To get a build that includes Modernizr.load(), as well as choosing\n * which tests to include, go to www.modernizr.com/download/\n *\n * Authors        Faruk Ates, Paul Irish, Alex Sexton\n * Contributors   Ryan Seddon, Ben Alman\n */\n\nwindow.Modernizr = (function( window, document, undefined ) {\n\n    var version = '2.8.3',\n\n    Modernizr = {},\n\n    /*>>cssclasses*/\n    // option for enabling the HTML classes to be added\n    enableClasses = true,\n    /*>>cssclasses*/\n\n    docElement = document.documentElement,\n\n    /**\n     * Create our \"modernizr\" element that we do most feature tests on.\n     */\n    mod = 'modernizr',\n    modElem = document.createElement(mod),\n    mStyle = modElem.style,\n\n    /**\n     * Create the input element for various Web Forms feature tests.\n     */\n    inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ ,\n\n    /*>>smile*/\n    smile = ':)',\n    /*>>smile*/\n\n    toString = {}.toString,\n\n    // TODO :: make the prefixes more granular\n    /*>>prefixes*/\n    // List of property values to set for css tests. See ticket #21\n    prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),\n    /*>>prefixes*/\n\n    /*>>domprefixes*/\n    // Following spec is to expose vendor-specific style properties as:\n    //   elem.style.WebkitBorderRadius\n    // and the following would be incorrect:\n    //   elem.style.webkitBorderRadius\n\n    // Webkit ghosts their properties in lowercase but Opera & Moz do not.\n    // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+\n    //   erik.eae.net/archives/2008/03/10/21.48.10/\n\n    // More here: github.com/Modernizr/Modernizr/issues/issue/21\n    omPrefixes = 'Webkit Moz O ms',\n\n    cssomPrefixes = omPrefixes.split(' '),\n\n    domPrefixes = omPrefixes.toLowerCase().split(' '),\n    /*>>domprefixes*/\n\n    /*>>ns*/\n    ns = {'svg': 'http://www.w3.org/2000/svg'},\n    /*>>ns*/\n\n    tests = {},\n    inputs = {},\n    attrs = {},\n\n    classes = [],\n\n    slice = classes.slice,\n\n    featureName, // used in testing loop\n\n\n    /*>>teststyles*/\n    // Inject element with style element and some CSS rules\n    injectElementWithStyles = function( rule, callback, nodes, testnames ) {\n\n      var style, ret, node, docOverflow,\n          div = document.createElement('div'),\n          // After page load injecting a fake body doesn't work so check if body exists\n          body = document.body,\n          // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it.\n          fakeBody = body || document.createElement('body');\n\n      if ( parseInt(nodes, 10) ) {\n          // In order not to give false positives we create a node for each test\n          // This also allows the method to scale for unspecified uses\n          while ( nodes-- ) {\n              node = document.createElement('div');\n              node.id = testnames ? testnames[nodes] : mod + (nodes + 1);\n              div.appendChild(node);\n          }\n      }\n\n      // <style> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed\n      // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element\n      // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements.\n      // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx\n      // Documents served as xml will throw if using &shy; so use xml friendly encoded version. See issue #277\n      style = ['&#173;','<style id=\"s', mod, '\">', rule, '</style>'].join('');\n      div.id = mod;\n      // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.\n      // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270\n      (body ? div : fakeBody).innerHTML += style;\n      fakeBody.appendChild(div);\n      if ( !body ) {\n          //avoid crashing IE8, if background image is used\n          fakeBody.style.background = '';\n          //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible\n          fakeBody.style.overflow = 'hidden';\n          docOverflow = docElement.style.overflow;\n          docElement.style.overflow = 'hidden';\n          docElement.appendChild(fakeBody);\n      }\n\n      ret = callback(div, rule);\n      // If this is done after page load we don't want to remove the body so check if body exists\n      if ( !body ) {\n          fakeBody.parentNode.removeChild(fakeBody);\n          docElement.style.overflow = docOverflow;\n      } else {\n          div.parentNode.removeChild(div);\n      }\n\n      return !!ret;\n\n    },\n    /*>>teststyles*/\n\n    /*>>mq*/\n    // adapted from matchMedia polyfill\n    // by Scott Jehl and Paul Irish\n    // gist.github.com/786768\n    testMediaQuery = function( mq ) {\n\n      var matchMedia = window.matchMedia || window.msMatchMedia;\n      if ( matchMedia ) {\n        return matchMedia(mq) && matchMedia(mq).matches || false;\n      }\n\n      var bool;\n\n      injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) {\n        bool = (window.getComputedStyle ?\n                  getComputedStyle(node, null) :\n                  node.currentStyle)['position'] == 'absolute';\n      });\n\n      return bool;\n\n     },\n     /*>>mq*/\n\n\n    /*>>hasevent*/\n    //\n    // isEventSupported determines if a given element supports the given event\n    // kangax.github.com/iseventsupported/\n    //\n    // The following results are known incorrects:\n    //   Modernizr.hasEvent(\"webkitTransitionEnd\", elem) // false negative\n    //   Modernizr.hasEvent(\"textInput\") // in Webkit. github.com/Modernizr/Modernizr/issues/333\n    //   ...\n    isEventSupported = (function() {\n\n      var TAGNAMES = {\n        'select': 'input', 'change': 'input',\n        'submit': 'form', 'reset': 'form',\n        'error': 'img', 'load': 'img', 'abort': 'img'\n      };\n\n      function isEventSupported( eventName, element ) {\n\n        element = element || document.createElement(TAGNAMES[eventName] || 'div');\n        eventName = 'on' + eventName;\n\n        // When using `setAttribute`, IE skips \"unload\", WebKit skips \"unload\" and \"resize\", whereas `in` \"catches\" those\n        var isSupported = eventName in element;\n\n        if ( !isSupported ) {\n          // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element\n          if ( !element.setAttribute ) {\n            element = document.createElement('div');\n          }\n          if ( element.setAttribute && element.removeAttribute ) {\n            element.setAttribute(eventName, '');\n            isSupported = is(element[eventName], 'function');\n\n            // If property was created, \"remove it\" (by setting value to `undefined`)\n            if ( !is(element[eventName], 'undefined') ) {\n              element[eventName] = undefined;\n            }\n            element.removeAttribute(eventName);\n          }\n        }\n\n        element = null;\n        return isSupported;\n      }\n      return isEventSupported;\n    })(),\n    /*>>hasevent*/\n\n    // TODO :: Add flag for hasownprop ? didn't last time\n\n    // hasOwnProperty shim by kangax needed for Safari 2.0 support\n    _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;\n\n    if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {\n      hasOwnProp = function (object, property) {\n        return _hasOwnProperty.call(object, property);\n      };\n    }\n    else {\n      hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */\n        return ((property in object) && is(object.constructor.prototype[property], 'undefined'));\n      };\n    }\n\n    // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js\n    // es5.github.com/#x15.3.4.5\n\n    if (!Function.prototype.bind) {\n      Function.prototype.bind = function bind(that) {\n\n        var target = this;\n\n        if (typeof target != \"function\") {\n            throw new TypeError();\n        }\n\n        var args = slice.call(arguments, 1),\n            bound = function () {\n\n            if (this instanceof bound) {\n\n              var F = function(){};\n              F.prototype = target.prototype;\n              var self = new F();\n\n              var result = target.apply(\n                  self,\n                  args.concat(slice.call(arguments))\n              );\n              if (Object(result) === result) {\n                  return result;\n              }\n              return self;\n\n            } else {\n\n              return target.apply(\n                  that,\n                  args.concat(slice.call(arguments))\n              );\n\n            }\n\n        };\n\n        return bound;\n      };\n    }\n\n    /**\n     * setCss applies given styles to the Modernizr DOM node.\n     */\n    function setCss( str ) {\n        mStyle.cssText = str;\n    }\n\n    /**\n     * setCssAll extrapolates all vendor-specific css strings.\n     */\n    function setCssAll( str1, str2 ) {\n        return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));\n    }\n\n    /**\n     * is returns a boolean for if typeof obj is exactly type.\n     */\n    function is( obj, type ) {\n        return typeof obj === type;\n    }\n\n    /**\n     * contains returns a boolean for if substr is found within str.\n     */\n    function contains( str, substr ) {\n        return !!~('' + str).indexOf(substr);\n    }\n\n    /*>>testprop*/\n\n    // testProps is a generic CSS / DOM property test.\n\n    // In testing support for a given CSS property, it's legit to test:\n    //    `elem.style[styleName] !== undefined`\n    // If the property is supported it will return an empty string,\n    // if unsupported it will return undefined.\n\n    // We'll take advantage of this quick test and skip setting a style\n    // on our modernizr element, but instead just testing undefined vs\n    // empty string.\n\n    // Because the testing of the CSS property names (with \"-\", as\n    // opposed to the camelCase DOM properties) is non-portable and\n    // non-standard but works in WebKit and IE (but not Gecko or Opera),\n    // we explicitly reject properties with dashes so that authors\n    // developing in WebKit or IE first don't end up with\n    // browser-specific content by accident.\n\n    function testProps( props, prefixed ) {\n        for ( var i in props ) {\n            var prop = props[i];\n            if ( !contains(prop, \"-\") && mStyle[prop] !== undefined ) {\n                return prefixed == 'pfx' ? prop : true;\n            }\n        }\n        return false;\n    }\n    /*>>testprop*/\n\n    // TODO :: add testDOMProps\n    /**\n     * testDOMProps is a generic DOM property test; if a browser supports\n     *   a certain property, it won't return undefined for it.\n     */\n    function testDOMProps( props, obj, elem ) {\n        for ( var i in props ) {\n            var item = obj[props[i]];\n            if ( item !== undefined) {\n\n                // return the property name as a string\n                if (elem === false) return props[i];\n\n                // let's bind a function\n                if (is(item, 'function')){\n                  // default to autobind unless override\n                  return item.bind(elem || obj);\n                }\n\n                // return the unbound function or obj or value\n                return item;\n            }\n        }\n        return false;\n    }\n\n    /*>>testallprops*/\n    /**\n     * testPropsAll tests a list of DOM properties we want to check against.\n     *   We specify literally ALL possible (known and/or likely) properties on\n     *   the element including the non-vendor prefixed one, for forward-\n     *   compatibility.\n     */\n    function testPropsAll( prop, prefixed, elem ) {\n\n        var ucProp  = prop.charAt(0).toUpperCase() + prop.slice(1),\n            props   = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');\n\n        // did they call .prefixed('boxSizing') or are we just testing a prop?\n        if(is(prefixed, \"string\") || is(prefixed, \"undefined\")) {\n          return testProps(props, prefixed);\n\n        // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])\n        } else {\n          props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');\n          return testDOMProps(props, prefixed, elem);\n        }\n    }\n    /*>>testallprops*/\n\n\n    /**\n     * Tests\n     * -----\n     */\n\n    // The *new* flexbox\n    // dev.w3.org/csswg/css3-flexbox\n\n    tests['flexbox'] = function() {\n      return testPropsAll('flexWrap');\n    };\n\n    // The *old* flexbox\n    // www.w3.org/TR/2009/WD-css3-flexbox-20090723/\n\n    tests['flexboxlegacy'] = function() {\n        return testPropsAll('boxDirection');\n    };\n\n    // On the S60 and BB Storm, getContext exists, but always returns undefined\n    // so we actually have to call getContext() to verify\n    // github.com/Modernizr/Modernizr/issues/issue/97/\n\n    tests['canvas'] = function() {\n        var elem = document.createElement('canvas');\n        return !!(elem.getContext && elem.getContext('2d'));\n    };\n\n    tests['canvastext'] = function() {\n        return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));\n    };\n\n    // webk.it/70117 is tracking a legit WebGL feature detect proposal\n\n    // We do a soft detect which may false positive in order to avoid\n    // an expensive context creation: bugzil.la/732441\n\n    tests['webgl'] = function() {\n        return !!window.WebGLRenderingContext;\n    };\n\n    /*\n     * The Modernizr.touch test only indicates if the browser supports\n     *    touch events, which does not necessarily reflect a touchscreen\n     *    device, as evidenced by tablets running Windows 7 or, alas,\n     *    the Palm Pre / WebOS (touch) phones.\n     *\n     * Additionally, Chrome (desktop) used to lie about its support on this,\n     *    but that has since been rectified: crbug.com/36415\n     *\n     * We also test for Firefox 4 Multitouch Support.\n     *\n     * For more info, see: modernizr.github.com/Modernizr/touch.html\n     */\n\n    tests['touch'] = function() {\n        var bool;\n\n        if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {\n          bool = true;\n        } else {\n          injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) {\n            bool = node.offsetTop === 9;\n          });\n        }\n\n        return bool;\n    };\n\n\n    // geolocation is often considered a trivial feature detect...\n    // Turns out, it's quite tricky to get right:\n    //\n    // Using !!navigator.geolocation does two things we don't want. It:\n    //   1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513\n    //   2. Disables page caching in WebKit: webk.it/43956\n    //\n    // Meanwhile, in Firefox < 8, an about:config setting could expose\n    // a false positive that would throw an exception: bugzil.la/688158\n\n    tests['geolocation'] = function() {\n        return 'geolocation' in navigator;\n    };\n\n\n    tests['postmessage'] = function() {\n      return !!window.postMessage;\n    };\n\n\n    // Chrome incognito mode used to throw an exception when using openDatabase\n    // It doesn't anymore.\n    tests['websqldatabase'] = function() {\n      return !!window.openDatabase;\n    };\n\n    // Vendors had inconsistent prefixing with the experimental Indexed DB:\n    // - Webkit's implementation is accessible through webkitIndexedDB\n    // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB\n    // For speed, we don't test the legacy (and beta-only) indexedDB\n    tests['indexedDB'] = function() {\n      return !!testPropsAll(\"indexedDB\", window);\n    };\n\n    // documentMode logic from YUI to filter out IE8 Compat Mode\n    //   which false positives.\n    tests['hashchange'] = function() {\n      return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7);\n    };\n\n    // Per 1.6:\n    // This used to be Modernizr.historymanagement but the longer\n    // name has been deprecated in favor of a shorter and property-matching one.\n    // The old API is still available in 1.6, but as of 2.0 will throw a warning,\n    // and in the first release thereafter disappear entirely.\n    tests['history'] = function() {\n      return !!(window.history && history.pushState);\n    };\n\n    tests['draganddrop'] = function() {\n        var div = document.createElement('div');\n        return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);\n    };\n\n    // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10\n    // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17.\n    // FF10 still uses prefixes, so check for it until then.\n    // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/\n    tests['websockets'] = function() {\n        return 'WebSocket' in window || 'MozWebSocket' in window;\n    };\n\n\n    // css-tricks.com/rgba-browser-support/\n    tests['rgba'] = function() {\n        // Set an rgba() color and check the returned value\n\n        setCss('background-color:rgba(150,255,150,.5)');\n\n        return contains(mStyle.backgroundColor, 'rgba');\n    };\n\n    tests['hsla'] = function() {\n        // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally,\n        //   except IE9 who retains it as hsla\n\n        setCss('background-color:hsla(120,40%,100%,.5)');\n\n        return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');\n    };\n\n    tests['multiplebgs'] = function() {\n        // Setting multiple images AND a color on the background shorthand property\n        //  and then querying the style.background property value for the number of\n        //  occurrences of \"url(\" is a reliable method for detecting ACTUAL support for this!\n\n        setCss('background:url(https://),url(https://),red url(https://)');\n\n        // If the UA supports multiple backgrounds, there should be three occurrences\n        //   of the string \"url(\" in the return value for elemStyle.background\n\n        return (/(url\\s*\\(.*?){3}/).test(mStyle.background);\n    };\n\n\n\n    // this will false positive in Opera Mini\n    //   github.com/Modernizr/Modernizr/issues/396\n\n    tests['backgroundsize'] = function() {\n        return testPropsAll('backgroundSize');\n    };\n\n    tests['borderimage'] = function() {\n        return testPropsAll('borderImage');\n    };\n\n\n    // Super comprehensive table about all the unique implementations of\n    // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance\n\n    tests['borderradius'] = function() {\n        return testPropsAll('borderRadius');\n    };\n\n    // WebOS unfortunately false positives on this test.\n    tests['boxshadow'] = function() {\n        return testPropsAll('boxShadow');\n    };\n\n    // FF3.0 will false positive on this test\n    tests['textshadow'] = function() {\n        return document.createElement('div').style.textShadow === '';\n    };\n\n\n    tests['opacity'] = function() {\n        // Browsers that actually have CSS Opacity implemented have done so\n        //  according to spec, which means their return values are within the\n        //  range of [0.0,1.0] - including the leading zero.\n\n        setCssAll('opacity:.55');\n\n        // The non-literal . in this regex is intentional:\n        //   German Chrome returns this value as 0,55\n        // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632\n        return (/^0.55$/).test(mStyle.opacity);\n    };\n\n\n    // Note, Android < 4 will pass this test, but can only animate\n    //   a single property at a time\n    //   goo.gl/v3V4Gp\n    tests['cssanimations'] = function() {\n        return testPropsAll('animationName');\n    };\n\n\n    tests['csscolumns'] = function() {\n        return testPropsAll('columnCount');\n    };\n\n\n    tests['cssgradients'] = function() {\n        /**\n         * For CSS Gradients syntax, please see:\n         * webkit.org/blog/175/introducing-css-gradients/\n         * developer.mozilla.org/en/CSS/-moz-linear-gradient\n         * developer.mozilla.org/en/CSS/-moz-radial-gradient\n         * dev.w3.org/csswg/css3-images/#gradients-\n         */\n\n        var str1 = 'background-image:',\n            str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',\n            str3 = 'linear-gradient(left top,#9f9, white);';\n\n        setCss(\n             // legacy webkit syntax (FIXME: remove when syntax not in use anymore)\n              (str1 + '-webkit- '.split(' ').join(str2 + str1) +\n             // standard syntax             // trailing 'background-image:'\n              prefixes.join(str3 + str1)).slice(0, -str1.length)\n        );\n\n        return contains(mStyle.backgroundImage, 'gradient');\n    };\n\n\n    tests['cssreflections'] = function() {\n        return testPropsAll('boxReflect');\n    };\n\n\n    tests['csstransforms'] = function() {\n        return !!testPropsAll('transform');\n    };\n\n\n    tests['csstransforms3d'] = function() {\n\n        var ret = !!testPropsAll('perspective');\n\n        // Webkit's 3D transforms are passed off to the browser's own graphics renderer.\n        //   It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in\n        //   some conditions. As a result, Webkit typically recognizes the syntax but\n        //   will sometimes throw a false positive, thus we must do a more thorough check:\n        if ( ret && 'webkitPerspective' in docElement.style ) {\n\n          // Webkit allows this media query to succeed only if the feature is enabled.\n          // `@media (transform-3d),(-webkit-transform-3d){ ... }`\n          injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) {\n            ret = node.offsetLeft === 9 && node.offsetHeight === 3;\n          });\n        }\n        return ret;\n    };\n\n\n    tests['csstransitions'] = function() {\n        return testPropsAll('transition');\n    };\n\n\n    /*>>fontface*/\n    // @font-face detection routine by Diego Perini\n    // javascript.nwbox.com/CSSSupport/\n\n    // false positives:\n    //   WebOS github.com/Modernizr/Modernizr/issues/342\n    //   WP7   github.com/Modernizr/Modernizr/issues/538\n    tests['fontface'] = function() {\n        var bool;\n\n        injectElementWithStyles('@font-face {font-family:\"font\";src:url(\"https://\")}', function( node, rule ) {\n          var style = document.getElementById('smodernizr'),\n              sheet = style.sheet || style.styleSheet,\n              cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : '';\n\n          bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0;\n        });\n\n        return bool;\n    };\n    /*>>fontface*/\n\n    // CSS generated content detection\n    tests['generatedcontent'] = function() {\n        var bool;\n\n        injectElementWithStyles(['#',mod,'{font:0/0 a}#',mod,':after{content:\"',smile,'\";visibility:hidden;font:3px/1 a}'].join(''), function( node ) {\n          bool = node.offsetHeight >= 3;\n        });\n\n        return bool;\n    };\n\n\n\n    // These tests evaluate support of the video/audio elements, as well as\n    // testing what types of content they support.\n    //\n    // We're using the Boolean constructor here, so that we can extend the value\n    // e.g.  Modernizr.video     // true\n    //       Modernizr.video.ogg // 'probably'\n    //\n    // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845\n    //                     thx to NielsLeenheer and zcorpan\n\n    // Note: in some older browsers, \"no\" was a return value instead of empty string.\n    //   It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2\n    //   It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5\n\n    tests['video'] = function() {\n        var elem = document.createElement('video'),\n            bool = false;\n\n        // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224\n        try {\n            if ( bool = !!elem.canPlayType ) {\n                bool      = new Boolean(bool);\n                bool.ogg  = elem.canPlayType('video/ogg; codecs=\"theora\"')      .replace(/^no$/,'');\n\n                // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546\n                bool.h264 = elem.canPlayType('video/mp4; codecs=\"avc1.42E01E\"') .replace(/^no$/,'');\n\n                bool.webm = elem.canPlayType('video/webm; codecs=\"vp8, vorbis\"').replace(/^no$/,'');\n            }\n\n        } catch(e) { }\n\n        return bool;\n    };\n\n    tests['audio'] = function() {\n        var elem = document.createElement('audio'),\n            bool = false;\n\n        try {\n            if ( bool = !!elem.canPlayType ) {\n                bool      = new Boolean(bool);\n                bool.ogg  = elem.canPlayType('audio/ogg; codecs=\"vorbis\"').replace(/^no$/,'');\n                bool.mp3  = elem.canPlayType('audio/mpeg;')               .replace(/^no$/,'');\n\n                // Mimetypes accepted:\n                //   developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements\n                //   bit.ly/iphoneoscodecs\n                bool.wav  = elem.canPlayType('audio/wav; codecs=\"1\"')     .replace(/^no$/,'');\n                bool.m4a  = ( elem.canPlayType('audio/x-m4a;')            ||\n                              elem.canPlayType('audio/aac;'))             .replace(/^no$/,'');\n            }\n        } catch(e) { }\n\n        return bool;\n    };\n\n\n    // In FF4, if disabled, window.localStorage should === null.\n\n    // Normally, we could not test that directly and need to do a\n    //   `('localStorage' in window) && ` test first because otherwise Firefox will\n    //   throw bugzil.la/365772 if cookies are disabled\n\n    // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem\n    // will throw the exception:\n    //   QUOTA_EXCEEDED_ERRROR DOM Exception 22.\n    // Peculiarly, getItem and removeItem calls do not throw.\n\n    // Because we are forced to try/catch this, we'll go aggressive.\n\n    // Just FWIW: IE8 Compat mode supports these features completely:\n    //   www.quirksmode.org/dom/html5.html\n    // But IE8 doesn't support either with local files\n\n    tests['localstorage'] = function() {\n        try {\n            localStorage.setItem(mod, mod);\n            localStorage.removeItem(mod);\n            return true;\n        } catch(e) {\n            return false;\n        }\n    };\n\n    tests['sessionstorage'] = function() {\n        try {\n            sessionStorage.setItem(mod, mod);\n            sessionStorage.removeItem(mod);\n            return true;\n        } catch(e) {\n            return false;\n        }\n    };\n\n\n    tests['webworkers'] = function() {\n        return !!window.Worker;\n    };\n\n\n    tests['applicationcache'] = function() {\n        return !!window.applicationCache;\n    };\n\n\n    // Thanks to Erik Dahlstrom\n    tests['svg'] = function() {\n        return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;\n    };\n\n    // specifically for SVG inline in HTML, not within XHTML\n    // test page: paulirish.com/demo/inline-svg\n    tests['inlinesvg'] = function() {\n      var div = document.createElement('div');\n      div.innerHTML = '<svg/>';\n      return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;\n    };\n\n    // SVG SMIL animation\n    tests['smil'] = function() {\n        return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate')));\n    };\n\n    // This test is only for clip paths in SVG proper, not clip paths on HTML content\n    // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg\n\n    // However read the comments to dig into applying SVG clippaths to HTML content here:\n    //   github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491\n    tests['svgclippaths'] = function() {\n        return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));\n    };\n\n    /*>>webforms*/\n    // input features and input types go directly onto the ret object, bypassing the tests loop.\n    // Hold this guy to execute in a moment.\n    function webforms() {\n        /*>>input*/\n        // Run through HTML5's new input attributes to see if the UA understands any.\n        // We're using f which is the <input> element created early on\n        // Mike Taylr has created a comprehensive resource for testing these attributes\n        //   when applied to all input types:\n        //   miketaylr.com/code/input-type-attr.html\n        // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary\n\n        // Only input placeholder is tested while textarea's placeholder is not.\n        // Currently Safari 4 and Opera 11 have support only for the input placeholder\n        // Both tests are available in feature-detects/forms-placeholder.js\n        Modernizr['input'] = (function( props ) {\n            for ( var i = 0, len = props.length; i < len; i++ ) {\n                attrs[ props[i] ] = !!(props[i] in inputElem);\n            }\n            if (attrs.list){\n              // safari false positive's on datalist: webk.it/74252\n              // see also github.com/Modernizr/Modernizr/issues/146\n              attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement);\n            }\n            return attrs;\n        })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));\n        /*>>input*/\n\n        /*>>inputtypes*/\n        // Run through HTML5's new input types to see if the UA understands any.\n        //   This is put behind the tests runloop because it doesn't return a\n        //   true/false like all the other tests; instead, it returns an object\n        //   containing each input type with its corresponding true/false value\n\n        // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/\n        Modernizr['inputtypes'] = (function(props) {\n\n            for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {\n\n                inputElem.setAttribute('type', inputElemType = props[i]);\n                bool = inputElem.type !== 'text';\n\n                // We first check to see if the type we give it sticks..\n                // If the type does, we feed it a textual value, which shouldn't be valid.\n                // If the value doesn't stick, we know there's input sanitization which infers a custom UI\n                if ( bool ) {\n\n                    inputElem.value         = smile;\n                    inputElem.style.cssText = 'position:absolute;visibility:hidden;';\n\n                    if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) {\n\n                      docElement.appendChild(inputElem);\n                      defaultView = document.defaultView;\n\n                      // Safari 2-4 allows the smiley as a value, despite making a slider\n                      bool =  defaultView.getComputedStyle &&\n                              defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&\n                              // Mobile android web browser has false positive, so must\n                              // check the height to see if the widget is actually there.\n                              (inputElem.offsetHeight !== 0);\n\n                      docElement.removeChild(inputElem);\n\n                    } else if ( /^(search|tel)$/.test(inputElemType) ){\n                      // Spec doesn't define any special parsing or detectable UI\n                      //   behaviors so we pass these through as true\n\n                      // Interestingly, opera fails the earlier test, so it doesn't\n                      //  even make it here.\n\n                    } else if ( /^(url|email)$/.test(inputElemType) ) {\n                      // Real url and email support comes with prebaked validation.\n                      bool = inputElem.checkValidity && inputElem.checkValidity() === false;\n\n                    } else {\n                      // If the upgraded input compontent rejects the :) text, we got a winner\n                      bool = inputElem.value != smile;\n                    }\n                }\n\n                inputs[ props[i] ] = !!bool;\n            }\n            return inputs;\n        })('search tel url email datetime date month week time datetime-local number range color'.split(' '));\n        /*>>inputtypes*/\n    }\n    /*>>webforms*/\n\n\n    // End of test definitions\n    // -----------------------\n\n\n\n    // Run through all tests and detect their support in the current UA.\n    // todo: hypothetically we could be doing an array of tests and use a basic loop here.\n    for ( var feature in tests ) {\n        if ( hasOwnProp(tests, feature) ) {\n            // run the test, throw the return value into the Modernizr,\n            //   then based on that boolean, define an appropriate className\n            //   and push it into an array of classes we'll join later.\n            featureName  = feature.toLowerCase();\n            Modernizr[featureName] = tests[feature]();\n\n            classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);\n        }\n    }\n\n    /*>>webforms*/\n    // input tests need to run.\n    Modernizr.input || webforms();\n    /*>>webforms*/\n\n\n    /**\n     * addTest allows the user to define their own feature tests\n     * the result will be added onto the Modernizr object,\n     * as well as an appropriate className set on the html element\n     *\n     * @param feature - String naming the feature\n     * @param test - Function returning true if feature is supported, false if not\n     */\n     Modernizr.addTest = function ( feature, test ) {\n       if ( typeof feature == 'object' ) {\n         for ( var key in feature ) {\n           if ( hasOwnProp( feature, key ) ) {\n             Modernizr.addTest( key, feature[ key ] );\n           }\n         }\n       } else {\n\n         feature = feature.toLowerCase();\n\n         if ( Modernizr[feature] !== undefined ) {\n           // we're going to quit if you're trying to overwrite an existing test\n           // if we were to allow it, we'd do this:\n           //   var re = new RegExp(\"\\\\b(no-)?\" + feature + \"\\\\b\");\n           //   docElement.className = docElement.className.replace( re, '' );\n           // but, no rly, stuff 'em.\n           return Modernizr;\n         }\n\n         test = typeof test == 'function' ? test() : test;\n\n         if (typeof enableClasses !== \"undefined\" && enableClasses) {\n           docElement.className += ' ' + (test ? '' : 'no-') + feature;\n         }\n         Modernizr[feature] = test;\n\n       }\n\n       return Modernizr; // allow chaining.\n     };\n\n\n    // Reset modElem.cssText to nothing to reduce memory footprint.\n    setCss('');\n    modElem = inputElem = null;\n\n    /*>>shiv*/\n    /**\n     * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed\n     */\n    ;(function(window, document) {\n        /*jshint evil:true */\n        /** version */\n        var version = '3.7.0';\n\n        /** Preset options */\n        var options = window.html5 || {};\n\n        /** Used to skip problem elements */\n        var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;\n\n        /** Not all elements can be cloned in IE **/\n        var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;\n\n        /** Detect whether the browser supports default html5 styles */\n        var supportsHtml5Styles;\n\n        /** Name of the expando, to work with multiple documents or to re-shiv one document */\n        var expando = '_html5shiv';\n\n        /** The id for the the documents expando */\n        var expanID = 0;\n\n        /** Cached data for each document */\n        var expandoData = {};\n\n        /** Detect whether the browser supports unknown elements */\n        var supportsUnknownElements;\n\n        (function() {\n          try {\n            var a = document.createElement('a');\n            a.innerHTML = '<xyz></xyz>';\n            //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles\n            supportsHtml5Styles = ('hidden' in a);\n\n            supportsUnknownElements = a.childNodes.length == 1 || (function() {\n              // assign a false positive if unable to shiv\n              (document.createElement)('a');\n              var frag = document.createDocumentFragment();\n              return (\n                typeof frag.cloneNode == 'undefined' ||\n                typeof frag.createDocumentFragment == 'undefined' ||\n                typeof frag.createElement == 'undefined'\n              );\n            }());\n          } catch(e) {\n            // assign a false positive if detection fails => unable to shiv\n            supportsHtml5Styles = true;\n            supportsUnknownElements = true;\n          }\n\n        }());\n\n        /*--------------------------------------------------------------------------*/\n\n        /**\n         * Creates a style sheet with the given CSS text and adds it to the document.\n         * @private\n         * @param {Document} ownerDocument The document.\n         * @param {String} cssText The CSS text.\n         * @returns {StyleSheet} The style element.\n         */\n        function addStyleSheet(ownerDocument, cssText) {\n          var p = ownerDocument.createElement('p'),\n          parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;\n\n          p.innerHTML = 'x<style>' + cssText + '</style>';\n          return parent.insertBefore(p.lastChild, parent.firstChild);\n        }\n\n        /**\n         * Returns the value of `html5.elements` as an array.\n         * @private\n         * @returns {Array} An array of shived element node names.\n         */\n        function getElements() {\n          var elements = html5.elements;\n          return typeof elements == 'string' ? elements.split(' ') : elements;\n        }\n\n        /**\n         * Returns the data associated to the given document\n         * @private\n         * @param {Document} ownerDocument The document.\n         * @returns {Object} An object of data.\n         */\n        function getExpandoData(ownerDocument) {\n          var data = expandoData[ownerDocument[expando]];\n          if (!data) {\n            data = {};\n            expanID++;\n            ownerDocument[expando] = expanID;\n            expandoData[expanID] = data;\n          }\n          return data;\n        }\n\n        /**\n         * returns a shived element for the given nodeName and document\n         * @memberOf html5\n         * @param {String} nodeName name of the element\n         * @param {Document} ownerDocument The context document.\n         * @returns {Object} The shived element.\n         */\n        function createElement(nodeName, ownerDocument, data){\n          if (!ownerDocument) {\n            ownerDocument = document;\n          }\n          if(supportsUnknownElements){\n            return ownerDocument.createElement(nodeName);\n          }\n          if (!data) {\n            data = getExpandoData(ownerDocument);\n          }\n          var node;\n\n          if (data.cache[nodeName]) {\n            node = data.cache[nodeName].cloneNode();\n          } else if (saveClones.test(nodeName)) {\n            node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();\n          } else {\n            node = data.createElem(nodeName);\n          }\n\n          // Avoid adding some elements to fragments in IE < 9 because\n          // * Attributes like `name` or `type` cannot be set/changed once an element\n          //   is inserted into a document/fragment\n          // * Link elements with `src` attributes that are inaccessible, as with\n          //   a 403 response, will cause the tab/window to crash\n          // * Script elements appended to fragments will execute when their `src`\n          //   or `text` property is set\n          return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;\n        }\n\n        /**\n         * returns a shived DocumentFragment for the given document\n         * @memberOf html5\n         * @param {Document} ownerDocument The context document.\n         * @returns {Object} The shived DocumentFragment.\n         */\n        function createDocumentFragment(ownerDocument, data){\n          if (!ownerDocument) {\n            ownerDocument = document;\n          }\n          if(supportsUnknownElements){\n            return ownerDocument.createDocumentFragment();\n          }\n          data = data || getExpandoData(ownerDocument);\n          var clone = data.frag.cloneNode(),\n          i = 0,\n          elems = getElements(),\n          l = elems.length;\n          for(;i<l;i++){\n            clone.createElement(elems[i]);\n          }\n          return clone;\n        }\n\n        /**\n         * Shivs the `createElement` and `createDocumentFragment` methods of the document.\n         * @private\n         * @param {Document|DocumentFragment} ownerDocument The document.\n         * @param {Object} data of the document.\n         */\n        function shivMethods(ownerDocument, data) {\n          if (!data.cache) {\n            data.cache = {};\n            data.createElem = ownerDocument.createElement;\n            data.createFrag = ownerDocument.createDocumentFragment;\n            data.frag = data.createFrag();\n          }\n\n\n          ownerDocument.createElement = function(nodeName) {\n            //abort shiv\n            if (!html5.shivMethods) {\n              return data.createElem(nodeName);\n            }\n            return createElement(nodeName, ownerDocument, data);\n          };\n\n          ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +\n                                                          'var n=f.cloneNode(),c=n.createElement;' +\n                                                          'h.shivMethods&&(' +\n                                                          // unroll the `createElement` calls\n                                                          getElements().join().replace(/[\\w\\-]+/g, function(nodeName) {\n            data.createElem(nodeName);\n            data.frag.createElement(nodeName);\n            return 'c(\"' + nodeName + '\")';\n          }) +\n            ');return n}'\n                                                         )(html5, data.frag);\n        }\n\n        /*--------------------------------------------------------------------------*/\n\n        /**\n         * Shivs the given document.\n         * @memberOf html5\n         * @param {Document} ownerDocument The document to shiv.\n         * @returns {Document} The shived document.\n         */\n        function shivDocument(ownerDocument) {\n          if (!ownerDocument) {\n            ownerDocument = document;\n          }\n          var data = getExpandoData(ownerDocument);\n\n          if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {\n            data.hasCSS = !!addStyleSheet(ownerDocument,\n                                          // corrects block display not defined in IE6/7/8/9\n                                          'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +\n                                            // adds styling not present in IE6/7/8/9\n                                            'mark{background:#FF0;color:#000}' +\n                                            // hides non-rendered elements\n                                            'template{display:none}'\n                                         );\n          }\n          if (!supportsUnknownElements) {\n            shivMethods(ownerDocument, data);\n          }\n          return ownerDocument;\n        }\n\n        /*--------------------------------------------------------------------------*/\n\n        /**\n         * The `html5` object is exposed so that more elements can be shived and\n         * existing shiving can be detected on iframes.\n         * @type Object\n         * @example\n         *\n         * // options can be changed before the script is included\n         * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };\n         */\n        var html5 = {\n\n          /**\n           * An array or space separated string of node names of the elements to shiv.\n           * @memberOf html5\n           * @type Array|String\n           */\n          'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video',\n\n          /**\n           * current version of html5shiv\n           */\n          'version': version,\n\n          /**\n           * A flag to indicate that the HTML5 style sheet should be inserted.\n           * @memberOf html5\n           * @type Boolean\n           */\n          'shivCSS': (options.shivCSS !== false),\n\n          /**\n           * Is equal to true if a browser supports creating unknown/HTML5 elements\n           * @memberOf html5\n           * @type boolean\n           */\n          'supportsUnknownElements': supportsUnknownElements,\n\n          /**\n           * A flag to indicate that the document's `createElement` and `createDocumentFragment`\n           * methods should be overwritten.\n           * @memberOf html5\n           * @type Boolean\n           */\n          'shivMethods': (options.shivMethods !== false),\n\n          /**\n           * A string to describe the type of `html5` object (\"default\" or \"default print\").\n           * @memberOf html5\n           * @type String\n           */\n          'type': 'default',\n\n          // shivs the document according to the specified `html5` object options\n          'shivDocument': shivDocument,\n\n          //creates a shived element\n          createElement: createElement,\n\n          //creates a shived documentFragment\n          createDocumentFragment: createDocumentFragment\n        };\n\n        /*--------------------------------------------------------------------------*/\n\n        // expose html5\n        window.html5 = html5;\n\n        // shiv the document\n        shivDocument(document);\n\n    }(this, document));\n    /*>>shiv*/\n\n    // Assign private properties to the return object with prefix\n    Modernizr._version      = version;\n\n    // expose these for the plugin API. Look in the source for how to join() them against your input\n    /*>>prefixes*/\n    Modernizr._prefixes     = prefixes;\n    /*>>prefixes*/\n    /*>>domprefixes*/\n    Modernizr._domPrefixes  = domPrefixes;\n    Modernizr._cssomPrefixes  = cssomPrefixes;\n    /*>>domprefixes*/\n\n    /*>>mq*/\n    // Modernizr.mq tests a given media query, live against the current state of the window\n    // A few important notes:\n    //   * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false\n    //   * A max-width or orientation query will be evaluated against the current state, which may change later.\n    //   * You must specify values. Eg. If you are testing support for the min-width media query use:\n    //       Modernizr.mq('(min-width:0)')\n    // usage:\n    // Modernizr.mq('only screen and (max-width:768)')\n    Modernizr.mq            = testMediaQuery;\n    /*>>mq*/\n\n    /*>>hasevent*/\n    // Modernizr.hasEvent() detects support for a given event, with an optional element to test on\n    // Modernizr.hasEvent('gesturestart', elem)\n    Modernizr.hasEvent      = isEventSupported;\n    /*>>hasevent*/\n\n    /*>>testprop*/\n    // Modernizr.testProp() investigates whether a given style property is recognized\n    // Note that the property names must be provided in the camelCase variant.\n    // Modernizr.testProp('pointerEvents')\n    Modernizr.testProp      = function(prop){\n        return testProps([prop]);\n    };\n    /*>>testprop*/\n\n    /*>>testallprops*/\n    // Modernizr.testAllProps() investigates whether a given style property,\n    //   or any of its vendor-prefixed variants, is recognized\n    // Note that the property names must be provided in the camelCase variant.\n    // Modernizr.testAllProps('boxSizing')\n    Modernizr.testAllProps  = testPropsAll;\n    /*>>testallprops*/\n\n\n    /*>>teststyles*/\n    // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards\n    // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })\n    Modernizr.testStyles    = injectElementWithStyles;\n    /*>>teststyles*/\n\n\n    /*>>prefixed*/\n    // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input\n    // Modernizr.prefixed('boxSizing') // 'MozBoxSizing'\n\n    // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style.\n    // Return values will also be the camelCase variant, if you need to translate that to hypenated style use:\n    //\n    //     str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');\n\n    // If you're trying to ascertain which transition end event to bind to, you might do something like...\n    //\n    //     var transEndEventNames = {\n    //       'WebkitTransition' : 'webkitTransitionEnd',\n    //       'MozTransition'    : 'transitionend',\n    //       'OTransition'      : 'oTransitionEnd',\n    //       'msTransition'     : 'MSTransitionEnd',\n    //       'transition'       : 'transitionend'\n    //     },\n    //     transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];\n\n    Modernizr.prefixed      = function(prop, obj, elem){\n      if(!obj) {\n        return testPropsAll(prop, 'pfx');\n      } else {\n        // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'\n        return testPropsAll(prop, obj, elem);\n      }\n    };\n    /*>>prefixed*/\n\n\n    /*>>cssclasses*/\n    // Remove \"no-js\" class from <html> element, if it exists:\n    docElement.className = docElement.className.replace(/(^|\\s)no-js(\\s|$)/, '$1$2') +\n\n                            // Add the new classes to the <html> element.\n                            (enableClasses ? ' js ' + classes.join(' ') : '');\n    /*>>cssclasses*/\n\n    return Modernizr;\n\n})(this, this.document);\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/Home/About.cshtml",
    "content": "﻿@{\r\n    ViewBag.Title = \"About\";\r\n}\r\n<h2>@ViewBag.Title.</h2>\r\n\r\n<p>This is the website of the Ninja Academy. Use the search form to find our students</p>\r\n\r\n<img src=\"~/Content/academy.jpeg\" />\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/Home/Contact.cshtml",
    "content": "﻿@{\r\n    ViewBag.Title = \"Contact\";\r\n}\r\n<h2>@ViewBag.Title.</h2>\r\n<h3>@ViewBag.Message</h3>\r\n\r\n<address>\r\n    Ninja Academy<br />\r\n    1 Place of the senin<br />\r\n    <abbr title=\"Phone\">P:</abbr>\r\n    042.000.1337\r\n</address>\r\n\r\n<address>\r\n    <strong>Teacher frank: </strong> <a href=\"mailto:frank.umino@ninja.hack\">frank.umino@ninja.hack</a> / <a href=\"mailto:frank@academy.ninja.lan\">frank@academy.ninja.lan</a><br />\r\n    <strong>Teacher olivia: </strong> <a href=\"mailto:olivia.davis@ninja.hack\">olivia.davis@ninja.hacker</a> / <a href=\"mailto:olivia@academy.ninja.lan\">olivia@academy.ninja.lan</a>\r\n</address>"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/Home/Index.cshtml",
    "content": "﻿@{\r\n    ViewBag.Title = \"Home Page\";\r\n}\r\n\r\n<div class=\"jumbotron\">\r\n    <h1>Academy.Ninja.Lan</h1>\r\n    <p class=\"lead\">Welcome to the website of the ninja academy.</p>\r\n    <img src=\"~/Content/logo.jpeg\" />\r\n</div>\r\n\r\n\r\n<!-- <div class=\"row\">\r\n    <div class=\"col-md-4\">\r\n        <h2>Getting started</h2>\r\n        <p>\r\n            ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that\r\n            enables a clean separation of concerns and gives you full control over markup\r\n            for enjoyable, agile development.\r\n        </p>\r\n        <p><a class=\"btn btn-default\" href=\"https://go.microsoft.com/fwlink/?LinkId=301865\">Learn more &raquo;</a></p>\r\n    </div>\r\n    <div class=\"col-md-4\">\r\n        <h2>Web Hosting</h2>\r\n        <p>You can easily find a web hosting company that offers the right mix of features and price for your applications.</p>\r\n        <p><a class=\"btn btn-default\" href=\"https://go.microsoft.com/fwlink/?LinkId=301867\">Learn more &raquo;</a></p>\r\n    </div>\r\n</div>\r\n-->"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/Shared/Error.cshtml",
    "content": "﻿<!DOCTYPE html>\r\n<html>\r\n<head>\r\n    <meta name=\"viewport\" content=\"width=device-width\" />\r\n    <title>Error</title>\r\n</head>\r\n<body>\r\n    <hgroup>\r\n        <h1>Error.</h1>\r\n        <h2>An error occurred while processing your request.</h2>\r\n    </hgroup>\r\n</body>\r\n</html>\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/Shared/_Layout.cshtml",
    "content": "﻿<!DOCTYPE html>\r\n<html>\r\n<head>\r\n    <meta charset=\"utf-8\" />\r\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n    <title>@ViewBag.Title - NHA - Ninja Hacker Academy</title>\r\n    @Styles.Render(\"~/Content/css\")\r\n    @Scripts.Render(\"~/bundles/modernizr\")\r\n</head>\r\n<body>\r\n    <div class=\"navbar navbar-inverse navbar-fixed-top\">\r\n        <div class=\"container\">\r\n            <div class=\"navbar-header\">\r\n                <button type=\"button\" class=\"navbar-toggle\" data-toggle=\"collapse\" data-target=\".navbar-collapse\">\r\n                    <span class=\"icon-bar\"></span>\r\n                    <span class=\"icon-bar\"></span>\r\n                    <span class=\"icon-bar\"></span>\r\n                </button>\r\n                @Html.ActionLink(\"NHA - Ninja Hacker Academy\", \"Index\", \"Home\", new { area = \"\" }, new { @class = \"navbar-brand\" })\r\n            </div>\r\n            <div class=\"navbar-collapse collapse\">\r\n                <ul class=\"nav navbar-nav\">\r\n                    <li>@Html.ActionLink(\"Home\", \"Index\", \"Home\")</li>\r\n                    <li>@Html.ActionLink(\"List of students\", \"Index\", \"Students\")</li>\r\n                    <li>@Html.ActionLink(\"About\", \"About\", \"Home\")</li>\r\n                    <li>@Html.ActionLink(\"Contact\", \"Contact\", \"Home\")</li>\r\n                </ul>\r\n            </div>\r\n        </div>\r\n    </div>\r\n    <div class=\"container body-content\">\r\n        @RenderBody()\r\n        <hr />\r\n        <footer>\r\n            <p>&copy; @DateTime.Now.Year - Ninja Hacker Academy Webpage</p>\r\n        </footer>\r\n    </div>\r\n\r\n    @Scripts.Render(\"~/bundles/jquery\")\r\n    @Scripts.Render(\"~/bundles/bootstrap\")\r\n    @RenderSection(\"scripts\", required: false)\r\n</body>\r\n</html>\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/Students/Create.cshtml",
    "content": "﻿@model adrutro.Models.Student\r\n\r\n@{\r\n    ViewBag.Title = \"Create\";\r\n}\r\n\r\n<h2>Create</h2>\r\n\r\n\r\n@using (Html.BeginForm()) \r\n{\r\n    @Html.AntiForgeryToken()\r\n    \r\n<div class=\"form-horizontal\">\r\n    <h4>Student</h4>\r\n    <hr />\r\n    @Html.ValidationSummary(true, \"\", new { @class = \"text-danger\" })\r\n    <div class=\"form-group\">\r\n        @Html.LabelFor(model => model.Id, htmlAttributes: new { @class = \"control-label col-md-2\" })\r\n        <div class=\"col-md-10\">\r\n            @Html.EditorFor(model => model.Id, new { htmlAttributes = new { @class = \"form-control\" } })\r\n            @Html.ValidationMessageFor(model => model.Id, \"\", new { @class = \"text-danger\" })\r\n        </div>\r\n    </div>\r\n\r\n    <div class=\"form-group\">\r\n        @Html.LabelFor(model => model.Firstname, htmlAttributes: new { @class = \"control-label col-md-2\" })\r\n        <div class=\"col-md-10\">\r\n            @Html.EditorFor(model => model.Firstname, new { htmlAttributes = new { @class = \"form-control\" } })\r\n            @Html.ValidationMessageFor(model => model.Firstname, \"\", new { @class = \"text-danger\" })\r\n        </div>\r\n    </div>\r\n\r\n    <div class=\"form-group\">\r\n        @Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = \"control-label col-md-2\" })\r\n        <div class=\"col-md-10\">\r\n            @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = \"form-control\" } })\r\n            @Html.ValidationMessageFor(model => model.LastName, \"\", new { @class = \"text-danger\" })\r\n        </div>\r\n    </div>\r\n\r\n    <div class=\"form-group\">\r\n        @Html.LabelFor(model => model.Team, htmlAttributes: new { @class = \"control-label col-md-2\" })\r\n        <div class=\"col-md-10\">\r\n            @Html.EditorFor(model => model.Team, new { htmlAttributes = new { @class = \"form-control\" } })\r\n            @Html.ValidationMessageFor(model => model.Team, \"\", new { @class = \"text-danger\" })\r\n        </div>\r\n    </div>\r\n\r\n    <div class=\"form-group\">\r\n        <div class=\"col-md-offset-2 col-md-10\">\r\n            <input type=\"submit\" value=\"Create\" class=\"btn btn-default\" />\r\n        </div>\r\n    </div>\r\n</div>\r\n}\r\n\r\n<div>\r\n    @Html.ActionLink(\"Back to List\", \"Index\")\r\n</div>\r\n\r\n@section Scripts {\r\n    @Scripts.Render(\"~/bundles/jqueryval\")\r\n}\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/Students/Delete.cshtml",
    "content": "﻿@model adrutro.Models.Student\r\n\r\n@{\r\n    ViewBag.Title = \"Delete\";\r\n}\r\n\r\n<h2>Delete</h2>\r\n\r\n<h3>Are you sure you want to delete this?</h3>\r\n<div>\r\n    <h4>Student</h4>\r\n    <hr />\r\n    <dl class=\"dl-horizontal\">\r\n        <dt>\r\n            @Html.DisplayNameFor(model => model.Firstname)\r\n        </dt>\r\n\r\n        <dd>\r\n            @Html.DisplayFor(model => model.Firstname)\r\n        </dd>\r\n\r\n        <dt>\r\n            @Html.DisplayNameFor(model => model.LastName)\r\n        </dt>\r\n\r\n        <dd>\r\n            @Html.DisplayFor(model => model.LastName)\r\n        </dd>\r\n\r\n        <dd>\r\n            @Html.DisplayNameFor(model => model.Team)\r\n        </dd>\r\n\r\n        <dd>\r\n            @Html.DisplayFor(model => model.Team)\r\n        </dd>\r\n\r\n    </dl>\r\n\r\n    @using (Html.BeginForm()) {\r\n        @Html.AntiForgeryToken()\r\n\r\n        <div class=\"form-actions no-color\">\r\n            <input type=\"submit\" value=\"Delete\" class=\"btn btn-default\" /> |\r\n            @Html.ActionLink(\"Back to List\", \"Index\")\r\n        </div>\r\n    }\r\n</div>\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/Students/Details.cshtml",
    "content": "﻿@model adrutro.Models.Student\r\n\r\n@{\r\n    ViewBag.Title = \"Details\";\r\n}\r\n\r\n<h2>Details</h2>\r\n\r\n<div>\r\n    <h4>Student</h4>\r\n    <hr />\r\n    <dl class=\"dl-horizontal\">\r\n        <dt>\r\n            @Html.DisplayNameFor(model => model.Firstname)\r\n        </dt>\r\n\r\n        <dd>\r\n            @Html.DisplayFor(model => model.Firstname)\r\n        </dd>\r\n\r\n        <dt>\r\n            @Html.DisplayNameFor(model => model.LastName)\r\n        </dt>\r\n\r\n        <dd>\r\n            @Html.DisplayFor(model => model.LastName)\r\n        </dd>\r\n\r\n        <dt>\r\n            @Html.DisplayNameFor(model => model.Team)\r\n        </dt>\r\n\r\n        <dd>\r\n            @Html.DisplayFor(model => model.Team)\r\n        </dd>\r\n\r\n    </dl>\r\n</div>\r\n<p>\r\n    @Html.ActionLink(\"Back to List\", \"Index\")\r\n</p>\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/Students/Edit.cshtml",
    "content": "﻿@model adrutro.Models.Student\r\n\r\n@{\r\n    ViewBag.Title = \"Edit\";\r\n}\r\n\r\n<h2>Edit</h2>\r\n\r\n\r\n@using (Html.BeginForm())\r\n{\r\n    @Html.AntiForgeryToken()\r\n    \r\n<div class=\"form-horizontal\">\r\n    <h4>Student</h4>\r\n    <hr />\r\n    @Html.ValidationSummary(true, \"\", new { @class = \"text-danger\" })\r\n    @Html.HiddenFor(model => model.Id)\r\n\r\n    <div class=\"form-group\">\r\n        @Html.LabelFor(model => model.Firstname, htmlAttributes: new { @class = \"control-label col-md-2\" })\r\n        <div class=\"col-md-10\">\r\n            @Html.EditorFor(model => model.Firstname, new { htmlAttributes = new { @class = \"form-control\" } })\r\n            @Html.ValidationMessageFor(model => model.Firstname, \"\", new { @class = \"text-danger\" })\r\n        </div>\r\n    </div>\r\n\r\n    <div class=\"form-group\">\r\n        @Html.LabelFor(model => model.LastName, htmlAttributes: new { @class = \"control-label col-md-2\" })\r\n        <div class=\"col-md-10\">\r\n            @Html.EditorFor(model => model.LastName, new { htmlAttributes = new { @class = \"form-control\" } })\r\n            @Html.ValidationMessageFor(model => model.LastName, \"\", new { @class = \"text-danger\" })\r\n        </div>\r\n    </div>\r\n\r\n    <div class=\"form-group\">\r\n        @Html.LabelFor(model => model.Team, htmlAttributes: new { @class = \"control-label col-md-2\" })\r\n        <div class=\"col-md-10\">\r\n            @Html.EditorFor(model => model.Team, new { htmlAttributes = new { @class = \"form-control\" } })\r\n            @Html.ValidationMessageFor(model => model.Team, \"\", new { @class = \"text-danger\" })\r\n        </div>\r\n    </div>\r\n\r\n    <div class=\"form-group\">\r\n        <div class=\"col-md-offset-2 col-md-10\">\r\n            <input type=\"submit\" value=\"Save\" class=\"btn btn-default\" />\r\n        </div>\r\n    </div>\r\n</div>\r\n}\r\n\r\n<div>\r\n    @Html.ActionLink(\"Back to List\", \"Index\")\r\n</div>\r\n\r\n@section Scripts {\r\n    @Scripts.Render(\"~/bundles/jqueryval\")\r\n}\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/Students/Index.cshtml",
    "content": "﻿@model IEnumerable<adrutro.Models.Student>\r\n\r\n@{\r\n    ViewBag.Title = \"Students\";\r\n}\r\n\r\n<h2>Students</h2>\r\n\r\n<p>\r\n    <form asp-controller=\"Students\" asp-action=\"Index\">\r\n        <p>\r\n            Search by name : <input type=\"text\" name=\"SearchString\" />\r\n            Order By :\r\n                   <select name=\"orderBy\">\r\n                       <option value=\"Firstname\">@Html.DisplayNameFor(model => model.Firstname)</option>\r\n                       <option value=\"LastName\">@Html.DisplayNameFor(model => model.LastName)</option>\r\n                       <option value=\"Team\">@Html.DisplayNameFor(model => model.Team)</option>\r\n                   </select>\r\n            <input type=\"submit\" value=\"Search\" />\r\n        </p>\r\n    </form>\r\n</p>\r\n<table class=\"table\">\r\n    <tr>\r\n        <th>\r\n            @Html.DisplayNameFor(model => model.Firstname)\r\n        </th>\r\n        <th>\r\n            @Html.DisplayNameFor(model => model.LastName)\r\n        </th>\r\n        <th>\r\n            @Html.DisplayNameFor(model => model.Team)\r\n        </th>\r\n        <th></th>\r\n    </tr>\r\n\r\n@foreach (var item in Model) {\r\n    <tr>\r\n        <td>\r\n            @Html.DisplayFor(modelItem => item.Firstname)\r\n        </td>\r\n        <td>\r\n            @Html.DisplayFor(modelItem => item.LastName)\r\n        </td>\r\n        <td>\r\n            @Html.DisplayFor(modelItem => item.Team)\r\n        </td>\r\n        <td>\r\n            @Html.ActionLink(\"Details\", \"Details\", new { id=item.Id })\r\n        </td>\r\n    </tr>\r\n}\r\n\r\n</table>\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/Web.config",
    "content": "﻿<?xml version=\"1.0\"?>\r\n\r\n<configuration>\r\n  <configSections>\r\n    <sectionGroup name=\"system.web.webPages.razor\" type=\"System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\">\r\n      <section name=\"host\" type=\"System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\" requirePermission=\"false\" />\r\n      <section name=\"pages\" type=\"System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\" requirePermission=\"false\" />\r\n    </sectionGroup>\r\n  </configSections>\r\n\r\n  <system.web.webPages.razor>\r\n    <host factoryType=\"System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\" />\r\n    <pages pageBaseType=\"System.Web.Mvc.WebViewPage\">\r\n      <namespaces>\r\n        <add namespace=\"System.Web.Mvc\" />\r\n        <add namespace=\"System.Web.Mvc.Ajax\" />\r\n        <add namespace=\"System.Web.Mvc.Html\" />\r\n        <add namespace=\"System.Web.Optimization\"/>\r\n        <add namespace=\"System.Web.Routing\" />\r\n        <add namespace=\"adrutro\" />\r\n      </namespaces>\r\n    </pages>\r\n  </system.web.webPages.razor>\r\n\r\n  <appSettings>\r\n    <add key=\"webpages:Enabled\" value=\"false\" />\r\n  </appSettings>\r\n\r\n  <system.webServer>\r\n    <handlers>\r\n      <remove name=\"BlockViewHandler\"/>\r\n      <add name=\"BlockViewHandler\" path=\"*\" verb=\"*\" preCondition=\"integratedMode\" type=\"System.Web.HttpNotFoundHandler\" />\r\n    </handlers>\r\n  </system.webServer>\r\n\r\n  <system.web>\r\n    <compilation>\r\n      <assemblies>\r\n        <add assembly=\"System.Web.Mvc, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35\" />\r\n      </assemblies>\r\n    </compilation>\r\n  </system.web>\r\n</configuration>\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Views/_ViewStart.cshtml",
    "content": "﻿@{\r\n    Layout = \"~/Views/Shared/_Layout.cshtml\";\r\n}\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/Web.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!--\r\n  For more information on how to configure your ASP.NET application, please visit\r\n  https://go.microsoft.com/fwlink/?LinkId=301880\r\n  -->\r\n<configuration>\r\n  <configSections>\r\n    <section name=\"entityFramework\" type=\"System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" requirePermission=\"false\" />\r\n    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->\r\n  </configSections>\r\n  <appSettings>\r\n    <add key=\"webpages:Version\" value=\"3.0.0.0\" />\r\n    <add key=\"webpages:Enabled\" value=\"false\" />\r\n    <add key=\"ClientValidationEnabled\" value=\"true\" />\r\n    <add key=\"UnobtrusiveJavaScriptEnabled\" value=\"true\" />\r\n  </appSettings>\r\n  <system.web>\r\n    <compilation targetFramework=\"4.7.2\" />\r\n    <httpRuntime targetFramework=\"4.7.2\" />\r\n  </system.web>\r\n  <runtime>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Antlr3.Runtime\" publicKeyToken=\"eb42632606e9261f\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-3.5.0.2\" newVersion=\"3.5.0.2\" />\r\n      </dependentAssembly>\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Newtonsoft.Json\" publicKeyToken=\"30ad4fe6b2a6aeed\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-12.0.0.0\" newVersion=\"12.0.0.0\" />\r\n      </dependentAssembly>\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Web.Optimization\" publicKeyToken=\"31bf3856ad364e35\" />\r\n        <bindingRedirect oldVersion=\"1.0.0.0-1.1.0.0\" newVersion=\"1.1.0.0\" />\r\n      </dependentAssembly>\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"WebGrease\" publicKeyToken=\"31bf3856ad364e35\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.6.5135.21930\" newVersion=\"1.6.5135.21930\" />\r\n      </dependentAssembly>\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Web.Helpers\" publicKeyToken=\"31bf3856ad364e35\" />\r\n        <bindingRedirect oldVersion=\"1.0.0.0-3.0.0.0\" newVersion=\"3.0.0.0\" />\r\n      </dependentAssembly>\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Web.WebPages\" publicKeyToken=\"31bf3856ad364e35\" />\r\n        <bindingRedirect oldVersion=\"1.0.0.0-3.0.0.0\" newVersion=\"3.0.0.0\" />\r\n      </dependentAssembly>\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Web.Mvc\" publicKeyToken=\"31bf3856ad364e35\" />\r\n        <bindingRedirect oldVersion=\"1.0.0.0-5.2.7.0\" newVersion=\"5.2.7.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n  <system.codedom>\r\n    <compilers>\r\n      <compiler language=\"c#;cs;csharp\" extension=\".cs\" type=\"Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" warningLevel=\"4\" compilerOptions=\"/langversion:default /nowarn:1659;1699;1701\" />\r\n      <compiler language=\"vb;vbs;visualbasic;vbscript\" extension=\".vb\" type=\"Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\" warningLevel=\"4\" compilerOptions=\"/langversion:default /nowarn:41008 /define:_MYTYPE=\\&quot;Web\\&quot; /optionInfer+\" />\r\n    </compilers>\r\n  </system.codedom>\r\n  <entityFramework>\r\n    <providers>\r\n      <provider invariantName=\"System.Data.SqlClient\" type=\"System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer\" />\r\n    </providers>\r\n    <defaultConnectionFactory type=\"System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework\">\r\n      <parameters>\r\n        <parameter value=\"mssqllocaldb\" />\r\n      </parameters>\r\n    </defaultConnectionFactory>\r\n  </entityFramework>\r\n  <connectionStrings>\r\n    <add name=\"academyEntities\" connectionString=\"metadata=res://*/Models.AcademyModel.csdl|res://*/Models.AcademyModel.ssdl|res://*/Models.AcademyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=sql.academy.ninja.lan;initial catalog=academy;user id=sa;password=sa_P@ssw0rd!N1nJ4hackaDemy;MultipleActiveResultSets=True;App=EntityFramework&quot;\" providerName=\"System.Data.EntityClient\" />\r\n  </connectionStrings>\r\n</configuration>\r\n<!--ProjectGuid: 90062988-1461-45EA-9AD7-027903B95D72-->"
  },
  {
    "path": "ad/NHA/files/wwwroot/bin/roslyn/Microsoft.CSharp.Core.targets",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <Import Project=\"Microsoft.Managed.Core.targets\"/>\r\n\r\n  <Target Name=\"CoreCompile\"\r\n          Inputs=\"$(MSBuildAllProjects);\r\n                  @(Compile);\r\n                  @(_CoreCompileResourceInputs);\r\n                  $(ApplicationIcon);\r\n                  $(AssemblyOriginatorKeyFile);\r\n                  @(ReferencePathWithRefAssemblies);\r\n                  @(CompiledLicenseFile);\r\n                  @(LinkResource);\r\n                  @(EmbeddedDocumentation);\r\n                  $(Win32Resource);\r\n                  $(Win32Manifest);\r\n                  @(CustomAdditionalCompileInputs);\r\n                  $(ResolvedCodeAnalysisRuleSet);\r\n                  @(AdditionalFiles);\r\n                  @(EmbeddedFiles)\"\r\n          Outputs=\"@(DocFileItem);\r\n                   @(IntermediateAssembly);\r\n                   @(IntermediateRefAssembly);\r\n                   @(_DebugSymbolsIntermediatePath);\r\n                   $(NonExistentFile);\r\n                   @(CustomAdditionalCompileOutputs)\"\r\n          Returns=\"@(CscCommandLineArgs)\"\r\n          DependsOnTargets=\"$(CoreCompileDependsOn);_BeforeVBCSCoreCompile\">\r\n    <!-- These two compiler warnings are raised when a reference is bound to a different version\r\n             than specified in the assembly reference version number.  MSBuild raises the same warning in this case,\r\n             so the compiler warning would be redundant. -->\r\n    <PropertyGroup Condition=\"('$(TargetFrameworkVersion)' != 'v1.0') and ('$(TargetFrameworkVersion)' != 'v1.1')\">\r\n      <NoWarn>$(NoWarn);1701;1702</NoWarn>\r\n    </PropertyGroup>\r\n\r\n    <PropertyGroup>\r\n      <!-- To match historical behavior, when inside VS11+ disable the warning from csc.exe indicating that no sources were passed in-->\r\n      <NoWarn Condition=\"'$(BuildingInsideVisualStudio)' == 'true' AND '$(VisualStudioVersion)' != '' AND '$(VisualStudioVersion)' &gt; '10.0'\">$(NoWarn);2008</NoWarn>\r\n    </PropertyGroup>\r\n\r\n    <PropertyGroup>\r\n      <!-- If the user has specified AppConfigForCompiler, we'll use it. If they have not, but they set UseAppConfigForCompiler,\r\n                 then we'll use AppConfig -->\r\n      <AppConfigForCompiler Condition=\"'$(AppConfigForCompiler)' == '' AND '$(UseAppConfigForCompiler)' == 'true'\">$(AppConfig)</AppConfigForCompiler>\r\n\r\n      <!-- If we are targeting winmdobj we want to specifically the pdbFile property since we do not want it to collide with the output of winmdexp-->\r\n      <PdbFile Condition=\"'$(PdbFile)' == '' AND '$(OutputType)' == 'winmdobj' AND '$(_DebugSymbolsProduced)' == 'true'\">$(IntermediateOutputPath)$(TargetName).compile.pdb</PdbFile>\r\n    </PropertyGroup>\r\n\r\n    <!-- Condition is to filter out the _CoreCompileResourceInputs so that it doesn't pass in culture resources to the compiler -->\r\n    <Csc Condition=\"'%(_CoreCompileResourceInputs.WithCulture)' != 'true'\"\r\n         AdditionalLibPaths=\"$(AdditionalLibPaths)\"\r\n         AddModules=\"@(AddModules)\"\r\n         AdditionalFiles=\"@(AdditionalFiles)\"\r\n         AllowUnsafeBlocks=\"$(AllowUnsafeBlocks)\"\r\n         Analyzers=\"@(Analyzer)\"\r\n         ApplicationConfiguration=\"$(AppConfigForCompiler)\"\r\n         BaseAddress=\"$(BaseAddress)\"\r\n         CheckForOverflowUnderflow=\"$(CheckForOverflowUnderflow)\"\r\n         ChecksumAlgorithm=\"$(ChecksumAlgorithm)\"\r\n         CodeAnalysisRuleSet=\"$(ResolvedCodeAnalysisRuleSet)\"\r\n         CodePage=\"$(CodePage)\"\r\n         DebugType=\"$(DebugType)\"\r\n         DefineConstants=\"$(DefineConstants)\"\r\n         DelaySign=\"$(DelaySign)\"\r\n         DisabledWarnings=\"$(NoWarn)\"\r\n         DocumentationFile=\"@(DocFileItem)\"\r\n         EmbedAllSources=\"$(EmbedAllSources)\"\r\n         EmbeddedFiles=\"@(EmbeddedFiles)\"\r\n         EmitDebugInformation=\"$(DebugSymbols)\"\r\n         EnvironmentVariables=\"$(CscEnvironment)\"\r\n         ErrorEndLocation=\"$(ErrorEndLocation)\"\r\n         ErrorLog=\"$(ErrorLog)\"\r\n         ErrorReport=\"$(ErrorReport)\"\r\n         Features=\"$(Features)\"\r\n         FileAlignment=\"$(FileAlignment)\"\r\n         GenerateFullPaths=\"$(GenerateFullPaths)\"\r\n         HighEntropyVA=\"$(HighEntropyVA)\"\r\n         Instrument=\"$(Instrument)\"\r\n         KeyContainer=\"$(KeyContainerName)\"\r\n         KeyFile=\"$(KeyOriginatorFile)\"\r\n         LangVersion=\"$(LangVersion)\"\r\n         LinkResources=\"@(LinkResource)\"\r\n         MainEntryPoint=\"$(StartupObject)\"\r\n         ModuleAssemblyName=\"$(ModuleAssemblyName)\"\r\n         NoConfig=\"true\"\r\n         NoLogo=\"$(NoLogo)\"\r\n         NoStandardLib=\"$(NoCompilerStandardLib)\"\r\n         NoWin32Manifest=\"$(NoWin32Manifest)\"\r\n         Optimize=\"$(Optimize)\"\r\n         Deterministic=\"$(Deterministic)\"\r\n         PublicSign=\"$(PublicSign)\"\r\n         OutputAssembly=\"@(IntermediateAssembly)\"\r\n         OutputRefAssembly=\"@(IntermediateRefAssembly)\"\r\n         PdbFile=\"$(PdbFile)\"\r\n         Platform=\"$(PlatformTarget)\"\r\n         Prefer32Bit=\"$(Prefer32Bit)\"\r\n         PreferredUILang=\"$(PreferredUILang)\"\r\n         ProvideCommandLineArgs=\"$(ProvideCommandLineArgs)\"\r\n         References=\"@(ReferencePathWithRefAssemblies)\"\r\n         ReportAnalyzer=\"$(ReportAnalyzer)\"\r\n         Resources=\"@(_CoreCompileResourceInputs);@(CompiledLicenseFile)\"\r\n         ResponseFiles=\"$(CompilerResponseFile)\"\r\n         RuntimeMetadataVersion=\"$(RuntimeMetadataVersion)\"\r\n         SharedCompilationId=\"$(SharedCompilationId)\"\r\n         SkipCompilerExecution=\"$(SkipCompilerExecution)\"\r\n         Sources=\"@(Compile)\"\r\n         SubsystemVersion=\"$(SubsystemVersion)\"\r\n         TargetType=\"$(OutputType)\"\r\n         ToolExe=\"$(CscToolExe)\"\r\n         ToolPath=\"$(CscToolPath)\"\r\n         TreatWarningsAsErrors=\"$(TreatWarningsAsErrors)\"\r\n         UseHostCompilerIfAvailable=\"$(UseHostCompilerIfAvailable)\"\r\n         UseSharedCompilation=\"$(UseSharedCompilation)\"\r\n         Utf8Output=\"$(Utf8Output)\"\r\n         VsSessionGuid=\"$(VsSessionGuid)\"\r\n         WarningLevel=\"$(WarningLevel)\"\r\n         WarningsAsErrors=\"$(WarningsAsErrors)\"\r\n         WarningsNotAsErrors=\"$(WarningsNotAsErrors)\"\r\n         Win32Icon=\"$(ApplicationIcon)\"\r\n         Win32Manifest=\"$(Win32Manifest)\"\r\n         Win32Resource=\"$(Win32Resource)\"\r\n         PathMap=\"$(PathMap)\"\r\n         SourceLink=\"$(SourceLink)\">\r\n      <Output TaskParameter=\"CommandLineArgs\" ItemName=\"CscCommandLineArgs\" />\r\n    </Csc>\r\n\r\n    <ItemGroup>\r\n      <_CoreCompileResourceInputs Remove=\"@(_CoreCompileResourceInputs)\" />\r\n    </ItemGroup>\r\n\r\n    <CallTarget Targets=\"$(TargetsTriggeredByCompilation)\" Condition=\"'$(TargetsTriggeredByCompilation)' != ''\" />\r\n  </Target>\r\n</Project>"
  },
  {
    "path": "ad/NHA/files/wwwroot/bin/roslyn/Microsoft.Managed.Core.targets",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <!--\r\n    Common targets for managed compilers.\r\n  -->\r\n  <UsingTask TaskName=\"Microsoft.CodeAnalysis.BuildTasks.MapSourceRoots\" AssemblyFile=\"$(MSBuildThisFileDirectory)Microsoft.Build.Tasks.CodeAnalysis.dll\" />\r\n\r\n  <Target Name=\"ShimReferencePathsWhenCommonTargetsDoesNotUnderstandReferenceAssemblies\"\r\n          BeforeTargets=\"CoreCompile\"\r\n          Condition=\"'@(ReferencePathWithRefAssemblies)' == ''\">\r\n    <!-- \r\n      FindReferenceAssembliesForReferences target in Common targets populate this item \r\n      since dev15.3. The compiler targets may be used (via NuGet package) on earlier MSBuilds. \r\n      If the ReferencePathWithRefAssemblies item is not populated, just use ReferencePaths \r\n      (implementation assemblies) as they are.\r\n      \r\n      Since XAML inner build runs CoreCompile directly (instead of Compile target),\r\n      it also doesn't invoke FindReferenceAssembliesForReferences listed in CompileDependsOn.\r\n      In that case we also populate ReferencePathWithRefAssemblies with implementation assemblies.\r\n    -->\r\n    <ItemGroup>\r\n      <ReferencePathWithRefAssemblies Include=\"@(ReferencePath)\" />\r\n    </ItemGroup>\r\n  </Target>\r\n\r\n  <Target Name=\"_BeforeVBCSCoreCompile\"\r\n          DependsOnTargets=\"ShimReferencePathsWhenCommonTargetsDoesNotUnderstandReferenceAssemblies\">\r\n    \r\n    <ItemGroup Condition=\"'$(TargetingClr2Framework)' == 'true'\">\r\n      <ReferencePathWithRefAssemblies>\r\n        <EmbedInteropTypes />\r\n      </ReferencePathWithRefAssemblies>\r\n    </ItemGroup>\r\n\r\n    <!-- Prefer32Bit was introduced in .NET 4.5. Set it to false if we are targeting 4.0 -->\r\n    <PropertyGroup Condition=\"('$(TargetFrameworkVersion)' == 'v4.0')\">\r\n      <Prefer32Bit>false</Prefer32Bit>\r\n    </PropertyGroup>\r\n\r\n    <!-- TODO: Remove this ItemGroup once it has been moved to \"_GenerateCompileInputs\" target in Microsoft.Common.CurrentVersion.targets.\r\n         https://github.com/dotnet/roslyn/issues/12223 -->\r\n    <ItemGroup Condition=\"('$(AdditionalFileItemNames)' != '')\">\r\n      <AdditionalFileItems Include=\"$(AdditionalFileItemNames)\" />\r\n      <AdditionalFiles Include=\"@(%(AdditionalFileItems.Identity))\" />\r\n    </ItemGroup>\r\n\r\n    <PropertyGroup Condition=\"'$(UseSharedCompilation)' == ''\">\r\n      <UseSharedCompilation>true</UseSharedCompilation>\r\n    </PropertyGroup>\r\n  </Target>\r\n\r\n  <!--\r\n    ========================\r\n    DeterministicSourcePaths\r\n    ========================\r\n    \r\n    Unless specified otherwise enable deterministic source root (PathMap) when building deterministically on CI server, but not for local builds.\r\n    In order for the debugger to find source files when debugging a locally built binary the PDB must contain original, unmapped local paths.\r\n  -->\r\n  <PropertyGroup>\r\n    <DeterministicSourcePaths Condition=\"'$(DeterministicSourcePaths)' == '' and '$(Deterministic)' == 'true' and '$(ContinuousIntegrationBuild)' == 'true'\">true</DeterministicSourcePaths>\r\n  </PropertyGroup>\r\n\r\n  <!--\r\n    ==========\r\n    SourceRoot\r\n    ==========\r\n\r\n    All source files of the project are expected to be located under one of the directories specified by SourceRoot item group.\r\n    This target collects all SourceRoots from various sources.\r\n\r\n    This target calculates final local path for each SourceRoot and sets SourceRoot.MappedPath metadata accordingly.\r\n    The final path is a path with deterministic prefix when DeterministicSourcePaths is true, and the original path otherwise.\r\n    In addition, the target validates and deduplicates the SourceRoot items.\r\n\r\n    InitializeSourceControlInformation is an msbuild target that ensures the SourceRoot items are populated from source control.\r\n    The target is available only if SourceControlInformationFeatureSupported is true.\r\n\r\n    A consumer of SourceRoot.MappedPath metadata, such as Source Link generator, shall depend on this target. \r\n  -->\r\n\r\n  <Target Name=\"InitializeSourceRootMappedPaths\"\r\n          DependsOnTargets=\"_InitializeSourceRootMappedPathsFromSourceControl\">\r\n\r\n    <ItemGroup Condition=\"'@(_MappedSourceRoot)' != ''\">\r\n      <_MappedSourceRoot Remove=\"@(_MappedSourceRoot)\" />\r\n    </ItemGroup>\r\n\r\n    <Microsoft.CodeAnalysis.BuildTasks.MapSourceRoots SourceRoots=\"@(SourceRoot)\" Deterministic=\"$(DeterministicSourcePaths)\">\r\n      <Output TaskParameter=\"MappedSourceRoots\" ItemName=\"_MappedSourceRoot\" />\r\n    </Microsoft.CodeAnalysis.BuildTasks.MapSourceRoots>\r\n\r\n    <ItemGroup>\r\n      <SourceRoot Remove=\"@(SourceRoot)\" />\r\n      <SourceRoot Include=\"@(_MappedSourceRoot)\" />\r\n    </ItemGroup>\r\n  </Target>\r\n\r\n  <!-- \r\n    Declare that target InitializeSourceRootMappedPaths that populates MappedPaths metadata on SourceRoot items is available.\r\n  -->\r\n  <PropertyGroup>\r\n    <SourceRootMappedPathsFeatureSupported>true</SourceRootMappedPathsFeatureSupported>\r\n  </PropertyGroup>\r\n\r\n  <!-- \r\n    If InitializeSourceControlInformation target isn't supported, we just continue without invoking that synchronization target. \r\n    We'll proceed with SourceRoot (and other source control properties) provided by the user (or blank).\r\n  -->\r\n  <Target Name=\"_InitializeSourceRootMappedPathsFromSourceControl\"\r\n          DependsOnTargets=\"InitializeSourceControlInformation\"\r\n          Condition=\"'$(SourceControlInformationFeatureSupported)' == 'true'\" />\r\n\r\n  <!-- \r\n    =======\r\n    PathMap\r\n    =======\r\n\r\n    If DeterministicSourcePaths is true sets PathMap based on SourceRoot.MappedPaths.\r\n\r\n    This target requires SourceRoot to be initialized in order to calculate the PathMap.\r\n    If SourceRoot doesn't contain any top-level roots an error is reported.\r\n  -->\r\n\r\n  <Target Name=\"_SetPathMapFromSourceRoots\"\r\n          DependsOnTargets=\"InitializeSourceRootMappedPaths\"\r\n          BeforeTargets=\"CoreCompile\"\r\n          Condition=\"'$(DeterministicSourcePaths)' == 'true'\">\r\n\r\n    <ItemGroup>\r\n      <_TopLevelSourceRoot Include=\"@(SourceRoot)\" Condition=\"'%(SourceRoot.NestedRoot)' == ''\"/>\r\n    </ItemGroup>\r\n\r\n    <PropertyGroup Condition=\"'@(_TopLevelSourceRoot)' != ''\">\r\n      <!-- TODO: Report error/warning if /pathmap doesn't cover all emitted source paths: https://github.com/dotnet/roslyn/issues/23969 -->\r\n\r\n      <!-- TODO: PathMap should accept and ignore empty mapping: https://github.com/dotnet/roslyn/issues/23523 -->\r\n      <PathMap Condition=\"'$(PathMap)' != ''\">,$(PathMap)</PathMap>\r\n\r\n      <!--\r\n        Prepend the SourceRoot.MappedPath values to PathMap, if it already has a value.\r\n        For each emitted source path the compiler applies the first mapping that matches the path.\r\n        PathMap values set previously will thus only be applied if the mapping provided by \r\n        SourceRoot.MappedPath doesn't match. Since SourceRoot.MappedPath is also used by SourceLink \r\n        preferring it over manually set PathMap ensures that PathMap is consistent with SourceLink.\r\n      \r\n        TODO: quote the paths to avoid misinterpreting ',' and '=' in them as separators, \r\n        but quoting doesn't currently work (see https://github.com/dotnet/roslyn/issues/22835).\r\n      -->\r\n      <PathMap>@(_TopLevelSourceRoot->'%(Identity)=%(MappedPath)', ',')$(PathMap)</PathMap>\r\n    </PropertyGroup>\r\n  </Target>\r\n\r\n</Project>"
  },
  {
    "path": "ad/NHA/files/wwwroot/bin/roslyn/Microsoft.VisualBasic.Core.targets",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<Project ToolsVersion=\"14.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <Import Project=\"Microsoft.Managed.Core.targets\"/>\r\n\r\n  <Target Name=\"CoreCompile\"\r\n          Inputs=\"$(MSBuildAllProjects);\r\n                  @(Compile);\r\n                  @(_CoreCompileResourceInputs);\r\n                  $(ApplicationIcon);\r\n                  $(AssemblyOriginatorKeyFile);\r\n                  @(ReferencePathWithRefAssemblies);\r\n                  @(CompiledLicenseFile);\r\n                  @(LinkResource);\r\n                  @(EmbeddedDocumentation);\r\n                  $(Win32Resource);\r\n                  $(Win32Manifest);\r\n                  @(CustomAdditionalCompileInputs);\r\n                  $(ResolvedCodeAnalysisRuleSet);\r\n                  @(AdditionalFiles);\r\n                  @(EmbeddedFiles)\"\r\n          Outputs=\"@(DocFileItem);\r\n                   @(IntermediateAssembly);\r\n                   @(IntermediateRefAssembly);\r\n                   @(_DebugSymbolsIntermediatePath);\r\n                   $(NonExistentFile);\r\n                   @(CustomAdditionalCompileOutputs)\"\r\n          Returns=\"@(VbcCommandLineArgs)\"\r\n          DependsOnTargets=\"$(CoreCompileDependsOn);_BeforeVBCSCoreCompile\">\r\n    <PropertyGroup>\r\n      <_NoWarnings Condition=\"'$(WarningLevel)' == '0'\">true</_NoWarnings>\r\n      <_NoWarnings Condition=\"'$(WarningLevel)' == '1'\">false</_NoWarnings>\r\n    </PropertyGroup>\r\n\r\n    <PropertyGroup>\r\n      <!-- If we are targeting winmdobj we want to specifically the pdbFile property since we do not want it to collide with the output of winmdexp-->\r\n      <PdbFile Condition=\"'$(PdbFile)' == '' AND '$(OutputType)' == 'winmdobj' AND '$(DebugSymbols)' == 'true'\">$(IntermediateOutputPath)$(TargetName).compile.pdb</PdbFile>\r\n    </PropertyGroup>\r\n\r\n    <!-- Condition is to filter out the _CoreCompileResourceInputs so that it doesn't pass in culture resources to the compiler -->\r\n    <Vbc Condition=\"'%(_CoreCompileResourceInputs.WithCulture)' != 'true'\"\r\n         AdditionalLibPaths=\"$(AdditionalLibPaths)\"\r\n         AddModules=\"@(AddModules)\"\r\n         AdditionalFiles=\"@(AdditionalFiles)\"\r\n         Analyzers=\"@(Analyzer)\"\r\n         BaseAddress=\"$(BaseAddress)\"\r\n         ChecksumAlgorithm=\"$(ChecksumAlgorithm)\"\r\n         CodeAnalysisRuleSet=\"$(ResolvedCodeAnalysisRuleSet)\"\r\n         CodePage=\"$(CodePage)\"\r\n         DebugType=\"$(DebugType)\"\r\n         DefineConstants=\"$(FinalDefineConstants)\"\r\n         DelaySign=\"$(DelaySign)\"\r\n         DisabledWarnings=\"$(NoWarn)\"\r\n         DocumentationFile=\"@(DocFileItem)\"\r\n         EmbedAllSources=\"$(EmbedAllSources)\"\r\n         EmbeddedFiles=\"@(EmbeddedFiles)\"\r\n         EmitDebugInformation=\"$(DebugSymbols)\"\r\n         EnvironmentVariables=\"$(VbcEnvironment)\"\r\n         ErrorLog=\"$(ErrorLog)\"\r\n         ErrorReport=\"$(ErrorReport)\"\r\n         Features=\"$(Features)\"\r\n         FileAlignment=\"$(FileAlignment)\"\r\n         GenerateDocumentation=\"$(GenerateDocumentation)\"\r\n         HighEntropyVA=\"$(HighEntropyVA)\"\r\n         Imports=\"@(Import)\"\r\n         Instrument=\"$(Instrument)\"\r\n         KeyContainer=\"$(KeyContainerName)\"\r\n         KeyFile=\"$(KeyOriginatorFile)\"\r\n         LangVersion=\"$(LangVersion)\"\r\n         LinkResources=\"@(LinkResource)\"\r\n         MainEntryPoint=\"$(StartupObject)\"\r\n         ModuleAssemblyName=\"$(ModuleAssemblyName)\"\r\n         NoConfig=\"true\"\r\n         NoStandardLib=\"$(NoCompilerStandardLib)\"\r\n         NoVBRuntimeReference=\"$(NoVBRuntimeReference)\"\r\n         NoWarnings=\"$(_NoWarnings)\"\r\n         NoWin32Manifest=\"$(NoWin32Manifest)\"\r\n         Optimize=\"$(Optimize)\"\r\n         Deterministic=\"$(Deterministic)\"\r\n         PublicSign=\"$(PublicSign)\"\r\n         OptionCompare=\"$(OptionCompare)\"\r\n         OptionExplicit=\"$(OptionExplicit)\"\r\n         OptionInfer=\"$(OptionInfer)\"\r\n         OptionStrict=\"$(OptionStrict)\"\r\n         OptionStrictType=\"$(OptionStrictType)\"\r\n         OutputAssembly=\"@(IntermediateAssembly)\"\r\n         OutputRefAssembly=\"@(IntermediateRefAssembly)\"\r\n         PdbFile=\"$(PdbFile)\"\r\n         Platform=\"$(PlatformTarget)\"\r\n         Prefer32Bit=\"$(Prefer32Bit)\"\r\n         PreferredUILang=\"$(PreferredUILang)\"\r\n         ProvideCommandLineArgs=\"$(ProvideCommandLineArgs)\"\r\n         References=\"@(ReferencePathWithRefAssemblies)\"\r\n         RemoveIntegerChecks=\"$(RemoveIntegerChecks)\"\r\n         ReportAnalyzer=\"$(ReportAnalyzer)\"\r\n         Resources=\"@(_CoreCompileResourceInputs);@(CompiledLicenseFile)\"\r\n         ResponseFiles=\"$(CompilerResponseFile)\"\r\n         RootNamespace=\"$(RootNamespace)\"\r\n         RuntimeMetadataVersion=\"$(RuntimeMetadataVersion)\"\r\n         SdkPath=\"$(FrameworkPathOverride)\"\r\n         SharedCompilationId=\"$(SharedCompilationId)\"\r\n         SkipCompilerExecution=\"$(SkipCompilerExecution)\"\r\n         Sources=\"@(Compile)\"\r\n         SubsystemVersion=\"$(SubsystemVersion)\"\r\n         TargetCompactFramework=\"$(TargetCompactFramework)\"\r\n         TargetType=\"$(OutputType)\"\r\n         ToolExe=\"$(VbcToolExe)\"\r\n         ToolPath=\"$(VbcToolPath)\"\r\n         TreatWarningsAsErrors=\"$(TreatWarningsAsErrors)\"\r\n         UseHostCompilerIfAvailable=\"$(UseHostCompilerIfAvailable)\"\r\n         UseSharedCompilation=\"$(UseSharedCompilation)\"\r\n         Utf8Output=\"$(Utf8Output)\"\r\n         VBRuntimePath=\"$(VBRuntimePath)\"\r\n         Verbosity=\"$(VbcVerbosity)\"\r\n         VsSessionGuid=\"$(VsSessionGuid)\"\r\n         WarningsAsErrors=\"$(WarningsAsErrors)\"\r\n         WarningsNotAsErrors=\"$(WarningsNotAsErrors)\"\r\n         Win32Icon=\"$(ApplicationIcon)\"\r\n         Win32Manifest=\"$(Win32Manifest)\"\r\n         Win32Resource=\"$(Win32Resource)\"\r\n         VBRuntime=\"$(VBRuntime)\"\r\n         PathMap=\"$(PathMap)\"\r\n         SourceLink=\"$(SourceLink)\">\r\n      <Output TaskParameter=\"CommandLineArgs\" ItemName=\"VbcCommandLineArgs\" />\r\n    </Vbc>\r\n    <ItemGroup>\r\n      <_CoreCompileResourceInputs Remove=\"@(_CoreCompileResourceInputs)\" />\r\n    </ItemGroup>\r\n\r\n    <CallTarget Targets=\"$(TargetsTriggeredByCompilation)\" Condition=\"'$(TargetsTriggeredByCompilation)' != ''\" />\r\n  </Target>\r\n</Project>"
  },
  {
    "path": "ad/NHA/files/wwwroot/bin/roslyn/VBCSCompiler.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <gcServer enabled=\"true\" />\r\n    <gcConcurrent enabled=\"false\" />\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n  <appSettings>\r\n    <!-- Number of seconds with no activity before the server times out and closes. \r\n         Set to -1 to never shut down the server. -->\r\n    <add key=\"keepalive\" value=\"600\" />\r\n  </appSettings>\r\n</configuration>"
  },
  {
    "path": "ad/NHA/files/wwwroot/bin/roslyn/csc.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <gcServer enabled=\"true\" />\r\n    <gcConcurrent enabled=\"false\" />\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n</configuration>"
  },
  {
    "path": "ad/NHA/files/wwwroot/bin/roslyn/csc.rsp",
    "content": "﻿# Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.\r\n\r\n# This file contains command-line options that the C#\r\n# command line compiler (CSC) will process as part\r\n# of every compilation, unless the \"/noconfig\" option\r\n# is specified. \r\n\r\n# Reference the common Framework libraries\r\n/r:Accessibility.dll\r\n/r:Microsoft.CSharp.dll\r\n/r:System.Configuration.dll\r\n/r:System.Configuration.Install.dll\r\n/r:System.Core.dll\r\n/r:System.Data.dll\r\n/r:System.Data.DataSetExtensions.dll\r\n/r:System.Data.Linq.dll\r\n/r:System.Data.OracleClient.dll\r\n/r:System.Deployment.dll\r\n/r:System.Design.dll\r\n/r:System.DirectoryServices.dll\r\n/r:System.dll\r\n/r:System.Drawing.Design.dll\r\n/r:System.Drawing.dll\r\n/r:System.EnterpriseServices.dll\r\n/r:System.Management.dll\r\n/r:System.Messaging.dll\r\n/r:System.Runtime.Remoting.dll\r\n/r:System.Runtime.Serialization.dll\r\n/r:System.Runtime.Serialization.Formatters.Soap.dll\r\n/r:System.Security.dll\r\n/r:System.ServiceModel.dll\r\n/r:System.ServiceModel.Web.dll\r\n/r:System.ServiceProcess.dll\r\n/r:System.Transactions.dll\r\n/r:System.Web.dll\r\n/r:System.Web.Extensions.Design.dll\r\n/r:System.Web.Extensions.dll\r\n/r:System.Web.Mobile.dll\r\n/r:System.Web.RegularExpressions.dll\r\n/r:System.Web.Services.dll\r\n/r:System.Windows.Forms.dll\r\n/r:System.Workflow.Activities.dll\r\n/r:System.Workflow.ComponentModel.dll\r\n/r:System.Workflow.Runtime.dll\r\n/r:System.Xml.dll\r\n/r:System.Xml.Linq.dll\r\n"
  },
  {
    "path": "ad/NHA/files/wwwroot/bin/roslyn/csi.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n</configuration>"
  },
  {
    "path": "ad/NHA/files/wwwroot/bin/roslyn/csi.rsp",
    "content": "﻿/r:System\r\n/r:System.Core\r\n/r:Microsoft.CSharp\r\n/r:System.ValueTuple.dll\r\n/u:System\r\n/u:System.IO\r\n/u:System.Collections.Generic\r\n/u:System.Console\r\n/u:System.Diagnostics\r\n/u:System.Dynamic\r\n/u:System.Linq\r\n/u:System.Linq.Expressions\r\n/u:System.Text\r\n/u:System.Threading.Tasks"
  },
  {
    "path": "ad/NHA/files/wwwroot/bin/roslyn/vbc.exe.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information. -->\r\n<configuration>\r\n  <startup>\r\n    <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6\" />\r\n  </startup>\r\n  <runtime>\r\n    <gcServer enabled=\"true\" />\r\n    <gcConcurrent enabled=\"false\" />\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.CSharp\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"Microsoft.CodeAnalysis.VisualBasic\" publicKeyToken=\"31bf3856ad364e35\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-2.9.0.0\" newVersion=\"2.9.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Collections.Immutable\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.2.3.0\" newVersion=\"1.2.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Console\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.FileVersionInfo\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Diagnostics.StackTrace\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.3.0\" newVersion=\"4.0.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Pipes\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Reflection.Metadata\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-1.4.3.0\" newVersion=\"1.4.3.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Threading.Thread\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Principal.Windows\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.ValueTuple\" publicKeyToken=\"cc7b13ffcd2ddd51\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.ReaderWriter\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.0.0\" newVersion=\"4.1.0.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.Compression\" publicKeyToken=\"b77a5c561934e089\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.1.2.0\" newVersion=\"4.1.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Xml.XPath.XDocument\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.Security.Cryptography.Primitives\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.1.0\" newVersion=\"4.0.1.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n    <assemblyBinding xmlns=\"urn:schemas-microsoft-com:asm.v1\">\r\n      <dependentAssembly>\r\n        <assemblyIdentity name=\"System.IO.FileSystem\" publicKeyToken=\"b03f5f7f11d50a3a\" culture=\"neutral\" />\r\n        <bindingRedirect oldVersion=\"0.0.0.0-4.0.2.0\" newVersion=\"4.0.2.0\" />\r\n      </dependentAssembly>\r\n    </assemblyBinding>\r\n  </runtime>\r\n</configuration>"
  },
  {
    "path": "ad/NHA/files/wwwroot/bin/roslyn/vbc.rsp",
    "content": "﻿# Copyright (c)  Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.\r\n\r\n# This file contains command-line options that the VB\r\n# command line compiler (VBC) will process as part\r\n# of every compilation, unless the \"/noconfig\" option\r\n# is specified. \r\n\r\n# Reference the common Framework libraries\r\n/r:Accessibility.dll\r\n/r:System.Configuration.dll\r\n/r:System.Configuration.Install.dll\r\n/r:System.Data.dll\r\n/r:System.Data.OracleClient.dll\r\n/r:System.Deployment.dll\r\n/r:System.Design.dll\r\n/r:System.DirectoryServices.dll\r\n/r:System.dll\r\n/r:System.Drawing.Design.dll\r\n/r:System.Drawing.dll\r\n/r:System.EnterpriseServices.dll\r\n/r:System.Management.dll\r\n/r:System.Messaging.dll\r\n/r:System.Runtime.Remoting.dll\r\n/r:System.Runtime.Serialization.Formatters.Soap.dll\r\n/r:System.Security.dll\r\n/r:System.ServiceProcess.dll\r\n/r:System.Transactions.dll\r\n/r:System.Web.dll\r\n/r:System.Web.Mobile.dll\r\n/r:System.Web.RegularExpressions.dll\r\n/r:System.Web.Services.dll\r\n/r:System.Windows.Forms.dll\r\n/r:System.XML.dll\r\n\r\n/r:System.Workflow.Activities.dll\r\n/r:System.Workflow.ComponentModel.dll\r\n/r:System.Workflow.Runtime.dll\r\n/r:System.Runtime.Serialization.dll\r\n/r:System.ServiceModel.dll\r\n\r\n/r:System.Core.dll\r\n/r:System.Xml.Linq.dll\r\n/r:System.Data.Linq.dll\r\n/r:System.Data.DataSetExtensions.dll\r\n/r:System.Web.Extensions.dll\r\n/r:System.Web.Extensions.Design.dll\r\n/r:System.ServiceModel.Web.dll\r\n\r\n# Import System and Microsoft.VisualBasic\r\n/imports:System\r\n/imports:Microsoft.VisualBasic\r\n/imports:System.Linq\r\n/imports:System.Xml.Linq\r\n\r\n/optioninfer+\r\n"
  },
  {
    "path": "ad/NHA/providers/aws/inventory",
    "content": "[default]\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=8dCT-6546541qsdDJjgScp\ndc02 ansible_host={{ip_range}}.20 dns_domain=dc02 dict_key=dc02 ansible_user=ansible ansible_password=Ufe-qsdaz789bVXSx9rk\nsrv01 ansible_host={{ip_range}}.21 dns_domain=dc02 dict_key=srv01 ansible_user=ansible ansible_password=EaqsdP+xh7sdfzaRk6j90\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02 ansible_user=ansible ansible_password=978i2pF43UqsdqsdJ-qsd\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc02 dict_key=srv03 ansible_user=ansible ansible_password=EalwxkfhqsdP+xh7sdfzaRk6j90\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/NHA/providers/aws/windows.tf",
    "content": "# t2.medium = 2cpu / 4GB\n# t2.large  = 2cpu / 8GB\n# t2.xlarge = 4cpu / 16GB\n\"dc01\" = {\n  name               = \"dc01\"\n  domain             = \"ninja.hack\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCT-6546541qsdDJjgScp\"\n}\n\"dc02\" = {\n  name               = \"dc02\"\n  domain             = \"academy.ninja.lan\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.20\"\n  password           = \"Ufe-qsdaz789bVXSx9rk\"\n}\n\"srv01\" = {\n  name               = \"srv01\"\n  domain             = \"academy.ninja.lan\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.21\"\n  password           = \"EaqsdP+xh7sdfzaRk6j90\"\n}\n\"srv02\" = {\n  name               = \"srv02\"\n  domain             = \"academy.ninja.lan\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.22\"\n  password           = \"978i2pF43UqsdqsdJ-qsd\"\n}\n\"srv03\" = {\n  name               = \"srv03\"\n  domain             = \"academy.ninja.lan\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.23\"\n  password           = \"EalwxkfhqsdP+xh7sdfzaRk6j90\"\n}"
  },
  {
    "path": "ad/NHA/providers/azure/inventory",
    "content": "[default]\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=8dCT-6546541qsdDJjgScp\ndc02 ansible_host={{ip_range}}.20 dns_domain=dc02 dict_key=dc02 ansible_user=ansible ansible_password=Ufe-qsdaz789bVXSx9rk\nsrv01 ansible_host={{ip_range}}.21 dns_domain=dc02 dict_key=srv01 ansible_user=ansible ansible_password=EaqsdP+xh7sdfzaRk6j90\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02 ansible_user=ansible ansible_password=978i2pF43UqsdqsdJ-qsd\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc02 dict_key=srv03 ansible_user=ansible ansible_password=EalwxkfhqsdP+xh7sdfzaRk6j90\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/NHA/providers/azure/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"dc01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCT-6546541qsdDJjgScp\"\n  size               = \"Standard_B2s\"\n}\n\"dc02\" = {\n  name               = \"dc02\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.20\"\n  password           = \"Ufe-qsdaz789bVXSx9rk\"\n  size               = \"Standard_B2s\"\n}\n\"srv01\" = {\n  name               = \"srv01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.21\"\n  password           = \"EaqsdP+xh7sdfzaRk6j90\"\n  size               = \"Standard_B2s\"\n}\n\"srv02\" = {\n  name               = \"srv02\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.22\"\n  password           = \"978i2pF43UqsdqsdJ-qsd\"\n  size               = \"Standard_B2s\"\n}\n\"srv03\" = {\n  name               = \"srv03\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.23\"\n  password           = \"EalwxkfhqsdP+xh7sdfzaRk6j90\"\n  size               = \"Standard_B2s\"\n}"
  },
  {
    "path": "ad/NHA/providers/ludus/config.yml",
    "content": "ludus:\n  - vm_name: \"{{ range_id }}-NHA-DC01\"\n    hostname: \"{{ range_id }}-DC01\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 30\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-NHA-DC02\"\n    hostname: \"{{ range_id }}-DC02\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 31\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-NHA-SRV01\"\n    hostname: \"{{ range_id }}-SRV01\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 32\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-NHA-SRV02\"\n    hostname: \"{{ range_id }}-SRV02\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 33\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-NHA-SRV03\"\n    hostname: \"{{ range_id }}-SRV03\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 34\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n"
  },
  {
    "path": "ad/NHA/providers/ludus/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; ninja.local\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.30 dns_domain=dc01 dns_domain=dc02 dict_key=dc01\ndc02 ansible_host={{ip_range}}.31 dns_domain=dc02 dict_key=dc02\nsrv01 ansible_host={{ip_range}}.32 dns_domain=dc02 dict_key=srv01\nsrv02 ansible_host={{ip_range}}.33 dns_domain=dc02 dict_key=srv02\nsrv03 ansible_host={{ip_range}}.34 dns_domain=dc02 dict_key=srv03\n\n\n[all:vars]\nforce_dns_server=no\ndns_server={{ip_range}}.254\n\ndns_server_forwarder={{ip_range}}.254\n\nansible_user=localuser\nansible_password=password"
  },
  {
    "path": "ad/NHA/providers/proxmox/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; PROXMOX\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\ndc02 ansible_host={{ip_range}}.11 dns_domain=dc02 dict_key=dc02\nsrv01 ansible_host={{ip_range}}.21 dns_domain=dc02 dict_key=srv01\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc02 dict_key=srv03\n\n\n[all:vars]\nforce_dns_server=yes\ndns_server={{ip_range}}.1\n\n\n"
  },
  {
    "path": "ad/NHA/providers/proxmox/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"DC01\"\n  desc               = \"DC01 - windows server 2019 - {{ip_range}}.10\"\n  cores              = 2\n  memory             = 3096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.10/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"dc02\" = {\n  name               = \"DC02\"\n  desc               = \"DC02 - windows server 2019 - {{ip_range}}.11\"\n  cores              = 2\n  memory             = 3096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.11/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"srv01\" = {\n  name               = \"SRV01\"\n  desc               = \"SRV01 - windows server 2019 - {{ip_range}}.21\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.21/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"srv02\" = {\n  name               = \"SRV02\"\n  desc               = \"SRV02 - windows server 2019 - {{ip_range}}.22\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.22/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"srv03\" = {\n  name               = \"SRV03\"\n  desc               = \"SRV03 - windows server 2016 - {{ip_range}}.23\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.23/24\"\n  gateway            = \"{{ip_range}}.1\"\n}"
  },
  {
    "path": "ad/NHA/providers/virtualbox/Vagrantfile",
    "content": "boxes = [\n  { :name => \"NHA-DC01\",   :ip => \"{{ip_range}}.10\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  { :name => \"NHA-DC02\",   :ip => \"{{ip_range}}.20\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => 2, :mem => 3000},\n  { :name => \"NHA-SRV01\",  :ip => \"{{ip_range}}.21\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => 2, :mem => 5000},\n  { :name => \"NHA-SRV02\",  :ip => \"{{ip_range}}.22\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => 2, :mem => 5000},\n  { :name => \"NHA-SRV03\",  :ip => \"{{ip_range}}.23\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => 2, :mem => 3000}\n]\n"
  },
  {
    "path": "ad/NHA/providers/virtualbox/inventory",
    "content": "[default]\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\ndc02 ansible_host={{ip_range}}.20 dns_domain=dc02 dict_key=dc02\nsrv01 ansible_host={{ip_range}}.21 dns_domain=dc02 dict_key=srv01\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc02 dict_key=srv03\n"
  },
  {
    "path": "ad/NHA/providers/vmware/Vagrantfile",
    "content": "boxes = [\n  { :name => \"NHA-DC01\",   :ip => \"{{ip_range}}.10\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => \"2\", :mem => \"3000\"},\n  { :name => \"NHA-DC02\",   :ip => \"{{ip_range}}.20\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => \"2\", :mem => \"3000\"},\n  { :name => \"NHA-SRV01\",  :ip => \"{{ip_range}}.21\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => \"2\", :mem => \"5000\"},\n  { :name => \"NHA-SRV02\",  :ip => \"{{ip_range}}.22\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => \"2\", :mem => \"5000\"},\n  { :name => \"NHA-SRV03\",  :ip => \"{{ip_range}}.23\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => \"2\", :mem => \"3000\"}\n]\n"
  },
  {
    "path": "ad/NHA/providers/vmware/inventory",
    "content": "[default]\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\ndc02 ansible_host={{ip_range}}.20 dns_domain=dc02 dict_key=dc02\nsrv01 ansible_host={{ip_range}}.21 dns_domain=dc02 dict_key=srv01\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc02 dict_key=srv03\n"
  },
  {
    "path": "ad/NHA/providers/vmware_esxi/Vagrantfile",
    "content": "boxes = [\n  { :name => \"NHA-DC01\",   :ip => \"{{ip_range}}.10\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => \"2\", :mem => \"3000\"},\n  { :name => \"NHA-DC02\",   :ip => \"{{ip_range}}.20\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => \"2\", :mem => \"3000\"},\n  { :name => \"NHA-SRV01\",  :ip => \"{{ip_range}}.21\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => \"2\", :mem => \"5000\"},\n  { :name => \"NHA-SRV02\",  :ip => \"{{ip_range}}.22\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => \"2\", :mem => \"5000\"},\n  { :name => \"NHA-SRV03\",  :ip => \"{{ip_range}}.23\", :box => \"mayfly/windows_server2019\", :os => \"windows\", :cpus => \"2\", :mem => \"3000\"}\n]\n"
  },
  {
    "path": "ad/NHA/providers/vmware_esxi/inventory",
    "content": "[default]\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\ndc02 ansible_host={{ip_range}}.20 dns_domain=dc02 dict_key=dc02\nsrv01 ansible_host={{ip_range}}.21 dns_domain=dc02 dict_key=srv01\nsrv02 ansible_host={{ip_range}}.22 dns_domain=dc02 dict_key=srv02\nsrv03 ansible_host={{ip_range}}.23 dns_domain=dc02 dict_key=srv03\n"
  },
  {
    "path": "ad/NHA/scripts/constrained_delegation_use_any.ps1",
    "content": "# https://www.thehacker.recipes/ad/movement/kerberos/delegations/constrained#with-protocol-transition\nSet-ADUser -Identity \"frank\" -ServicePrincipalNames @{Add='eventlog/share.academy.ninja.lan'}\nGet-ADUser -Identity \"frank\" | Set-ADAccountControl -TrustedToAuthForDelegation $true\nSet-ADUser -Identity \"frank\" -Add @{'msDS-AllowedToDelegateTo'=@('eventlog/share.academy.ninja.lan','eventlog/share')}\n"
  },
  {
    "path": "ad/SCCM/README.md",
    "content": "# SCCM lab\n\n![SCCM overview](../../docs/img/SCCMLAB_overview.png)\n\n## Servers\n4 virtual machines with Windows Server 2019\n\n- **DC** :  Domain Controler \n- **MECM** : mecm primary site serer\n- **MSSQL** : mecm sql server\n- **CLIENT** : mecm client computer\n\nAll vms got defender activated\n\n## Prerequisites\n- The prerequisites for the lab are the same as GOAD lab (virtualbox/vmware, python, ansible,...)\n- The lab take 16GB for the vagrant image + 100GB for the 4 vms\n- The installation take environ 2,5 hours (with fiber connection)\n- The lab download multiple files during the install (windows iso, mecm installation package, mssql installation package, ...), be sure to have a good internet connection.\n\n## proxmox installation\n- In order to use the proxmox provider follow this :\n\n1) create a template with the windows_server2019_proxmox_cloudinit_uptodate.pkvars.hcl packer file (guide here: https://mayfly277.github.io/posts/GOAD-on-proxmox-part2-packer/) (note the id after the creation)\n\n2) create the variable file (ad/SCCM/providers/proxmox/terraform/variables.tf) by coping the template (ad/SCCM/providers/proxmox/terraform/variables.tf.template) and change the value according to your proxmox environnement\n\n3) on the provisioning computer :\n```bash\n./goad.sh -t check -l SCCM -p proxmox -m local\n./goad.sh -t install -l SCCM -p proxmox -m local\n```\n\n4) if something goes wrong (restart of the vms during install, etc...), you can rerun only ansible with -a\n```bash\n./goad.sh -t install -l SCCM -p proxmox -m local -a\n```"
  },
  {
    "path": "ad/SCCM/data/config.json",
    "content": "{\n\"lab\" : {\n    \"hosts\" : {\n        \"dc01\" : {\n            \"hostname\" : \"DC\",\n            \"type\" : \"dc\",\n            \"local_admin_password\": \"AZERTY*qsdfg\",\n            \"domain\" : \"sccm.lab\",\n            \"path\" : \"DC=sccm,DC=lab\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"SCCMLAB\\\\Domain Admins\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"SCCMLAB\\\\LocalAdmins\"\n                ]\n            },\n            \"scripts\" : [],\n            \"vulns\" : [\"disable_firewall\"]\n        },\n        \"srv01\" : {\n            \"hostname\" : \"MECM\",\n            \"type\" : \"server\",\n            \"local_admin_password\": \"NgtI75cKV+Pu\",\n            \"domain\" : \"sccm.lab\",\n            \"path\" : \"DC=sccm,DC=lab\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"SCCMLAB\\\\LocalAdmins\",\n                    \"SCCMLAB\\\\SCCM-Admins\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"SCCMLAB\\\\RDPUsers\"\n                ]\n            },\n            \"scripts\" : [],\n            \"vulns\" : [\"disable_firewall\"]\n        },\n        \"srv02\" : {\n            \"hostname\" : \"MSSQL\",\n            \"type\" : \"server\",\n            \"local_admin_password\": \"NgtazecKV+Pu\",\n            \"domain\" : \"sccm.lab\",\n            \"path\" : \"DC=sccm,DC=lab\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"SCCMLAB\\\\LocalAdmins\",\n                    \"SCCMLAB\\\\sccm-sql\",\n                    \"SCCMLAB\\\\MECM$\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"SCCMLAB\\\\RDPUsers\"\n                ]\n            },\n            \"scripts\" : [],\n            \"vulns\" : [\"disable_firewall\"],\n            \"mssql\":{\n                \"sa_password\": \"Sup1_sa_P@ssw0rd!\",\n                \"svcaccount\" : \"sccm-sql\",\n                \"sysadmins\" : [\n                    \"SCCMLAB\\\\administrator\",\n                    \"SCCMLAB\\\\sccm-sql\",\n                    \"SCCMLAB\\\\LocalAdmins\",\n                    \"SCCMLAB\\\\MECM$\"\n                ]\n            }\n        },\n        \"ws01\" : {\n            \"hostname\" : \"CLIENT\",\n            \"type\" : \"workstation\",\n            \"local_admin_password\": \"EP+xh7Rk6j90\",\n            \"domain\" : \"sccm.lab\",\n            \"path\" : \"DC=sccm,DC=lab\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"SCCMLAB\\\\LocalAdmins\",\n                    \"SCCMLAB\\\\eve\"\n                ]\n            },\n            \"Remote Desktop Users\" : [\n                \"SCCMLAB\\\\RDPUsers\"\n            ],\n            \"scripts\" : [],\n            \"vulns\" : [\"disable_firewall\"]\n        }\n    },\n    \"domains\" : {\n        \"sccm.lab\" : {\n            \"dc\": \"dc01\",\n            \"domain_password\" : \"AZERTY*qsdfg\",\n            \"netbios_name\": \"SCCMLAB\",\n            \"sccm\": {\n                \"site_code\": \"P01\",\n                \"sccm_server\": \"MECM\",\n                \"sccm_mssql_server\": \"MSSQL\",\n                \"clients\": [\"CLIENT\",\"MECM\",\"MSSQL\"],\n                \"pxe_pass\" : \"123456789\",\n                \"naa_user\" : \"sccm-naa\",\n                \"push_account\" : \"sccm-client-push\",\n                \"account_da\" : \"sccm-account-da\",\n                \"pxe_location\" : \"LDAP://CN=Computers,DC=sccm,DC=lab\",\n                \"pxe_admin_pass\": \"EP+xh7Rk6j90\",\n                \"admins\" : [\"SCCMLAB\\\\SCCM-Admins\"]\n            },\n            \"laps_path\": \"OU=Laps,DC=sccm,DC=lab\",\n            \"organisation_units\" : {},\n            \"groups\" : {\n                \"universal\" : {},\n                \"global\" : {\n                    \"LocalAdmins\" : {\n                        \"managed_by\" : \"bob\",\n                        \"path\" : \"CN=Users,DC=sccm,DC=lab\"\n                    },\n                    \"RDPUsers\" : {\n                        \"managed_by\" : \"bob\",\n                        \"path\" : \"CN=Users,DC=sccm,DC=lab\"\n                    },\n                    \"SCCM-Site-Server\" : {\n                        \"managed_by\" : \"alice\",\n                        \"path\" : \"CN=Users,DC=sccm,DC=lab\",\n                        \"members\" : [\"SCCMLAB\\\\MECM$\"]\n                    },\n                    \"SCCM-Admins\" : {\n                        \"managed_by\" : \"dave\",\n                        \"path\" : \"CN=Users,DC=sccm,DC=lab\"\n                    },\n                    \"SCCM-Managed-Device\" : {\n                        \"managed_by\" : \"alice\",\n                        \"path\" : \"CN=Users,DC=sccm,DC=lab\",\n                        \"members\" : [\"SCCMLAB\\\\CLIENT$\",\"SCCMLAB\\\\MECM$\",\"SCCMLAB\\\\MSSQL$\",\"SCCMLAB\\\\DC$\"]\n                    }\n                },\n                \"domainlocal\" : {}\n            },\n            \"multi_domain_groups_member\" : {},\n            \"acls\" : {},\n            \"users\" : {\n                \"alice\" : {\n                    \"firstname\"   : \"alice\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"whiteRabbit\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"alice\",\n                    \"groups\"      : [\"LocalAdmins\", \"Domain Admins\"],\n                    \"path\"        : \"CN=Users,DC=sccm,DC=lab\"\n                },\n                \"bob\" : {\n                    \"firstname\"   : \"bob\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"marley\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"bob - local admin\",\n                    \"groups\"      : [\"LocalAdmins\"],\n                    \"path\"        : \"CN=Users,DC=sccm,DC=lab\"\n                },\n                \"carol\" : {\n                    \"firstname\"   : \"carol\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"SCCMftw\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"carol - low user\",\n                    \"groups\"      : [\"RDPUsers\"],\n                    \"path\"        : \"CN=Users,DC=sccm,DC=lab\"\n                },\n                \"dave\" : {\n                    \"firstname\"   : \"dave\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"dragon\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"dave\",\n                    \"groups\"      : [\"SCCM-Admins\",\"RDPUsers\"],\n                    \"path\"        : \"CN=Users,DC=sccm,DC=lab\"\n                },\n                \"eve\" : {\n                    \"firstname\"   : \"eve\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"iloveyou\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"eve - admin on client\",\n                    \"groups\"      : [\"RDPUsers\"],\n                    \"path\"        : \"CN=Users,DC=sccm,DC=lab\"\n                },\n                \"franck\" : {\n                    \"firstname\"   : \"franck\",\n                    \"surname\"     : \"-\",\n                    \"password\"    : \"rockme\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"franck - low user\",\n                    \"groups\"      : [\"RDPUsers\"],\n                    \"path\"        : \"CN=Users,DC=sccm,DC=lab\"\n                },\n                \"sccm-client-push\" : {\n                    \"firstname\"   : \"sccm\",\n                    \"surname\"     : \"client-push\",\n                    \"password\"    : \"superman\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"client push account\",\n                    \"groups\"      : [\"LocalAdmins\"],\n                    \"path\"        : \"CN=Users,DC=sccm,DC=lab\"\n                },\n                \"sccm-account-da\" : {\n                    \"firstname\"   : \"sccm\",\n                    \"surname\"     : \"sccm da account\",\n                    \"password\"    : \"SCCM_D@-ftw_\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"sccm account\",\n                    \"groups\"      : [\"Domain Admins\"],\n                    \"path\"        : \"CN=Users,DC=sccm,DC=lab\"\n                },\n                \"sccm-naa\" : {\n                    \"firstname\"   : \"sccm\",\n                    \"surname\"     : \"naa\",\n                    \"password\"    : \"123456789\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"naa account\",\n                    \"groups\"      : [],\n                    \"path\"        : \"CN=Users,DC=sccm,DC=lab\"\n                },\n                \"sccm-sql\" : {\n                    \"firstname\"   : \"sccm\",\n                    \"surname\"     : \"sql\",\n                    \"password\"    : \"SCCM_SQL_SERVICEACCOUNT\",\n                    \"city\"        : \"-\",\n                    \"description\" : \"sql service\",\n                    \"groups\"      : [],\n                    \"path\"        : \"CN=Users,DC=sccm,DC=lab\",\n                    \"spns\"        : [\"MSSQLSvc/MSSQL.sccm.lab:1433\",\"MSSQLSvc/MSSQL.sccm.lab\"]\n                }\n            }\n        }\n    }\n}}"
  },
  {
    "path": "ad/SCCM/data/inventory",
    "content": "[all:vars]\n;sccm lab variables\nsql_instance_name=MSSQLSERVER\nsql_version=MSSQL_2022\n\n; administrator user\nadmin_user=administrator\n\n; domain_name : folder inside ad/\ndomain_name=SCCM\n\nforce_dns_server=no\ndns_server=x.x.x.x\ntwo_adapters=yes\n\n;dns server forwarder\ndns_server_forwarder=1.1.1.1\n\n; winrm connection (windows)\nansible_user=vagrant\nansible_password=vagrant\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n# ansible_winrm_transport=basic\n# ansible_port=5985\n\n; proxy settings (the lab need internet for some install, if you are behind a proxy you should set the proxy here)\nenable_http_proxy=no\nad_http_proxy=http://x.x.x.x:xxxx\nad_https_proxy=http://x.x.x.x:xxxx\n\n[elk_server:vars]\n; ssh connection (linux)\nansible_ssh_user=vagrant\nansible_ssh_private_key_file=./.vagrant/machines/elk/virtualbox/private_key\nansible_ssh_port=22\nansible_ssh_common_args='-o StrictHostKeyChecking=no'\n\n; LAB SCENARIO CONFIGURATION -----------------------------\n\n; computers inside domain (mandatory)\n; usage : build.yml, ad-relations.yml, ad-servers.yml, vulnerabilities.yml\n[domain]\ndc01\nsrv01\nsrv02\nws01\n\n; domain controler (mandatory)\n; usage : ad-acl.yml, ad-data.yml, ad-relations.yml, laps.yml\n[dc]\ndc01\n\n; domain server to enroll (mandatory if you want servers)\n; usage : ad-data.yml, ad-servers.yml, laps.yml\n[server]\nsrv01\nsrv02\n\n; workstation to enroll (mandatory if you want workstation)\n; usage : ad-servers.yml, laps.yml\n[workstation]\nws01\n\n; parent domain controler (mandatory)\n; usage : ad-servers.yml\n[parent_dc]\ndc01\n\n; child domain controler (need a fqdn child_name.parent_name)\n; usage : ad-servers.yml\n[child_dc]\n\n; external trust, need domain trust entry in config (bidirectionnal)\n; usage : ad-trusts.yml\n[trust]\n\n; install adcs\n; usage : adcs.yml\n[adcs]\n\n; install custom template (dc)\n; usage : adcs.yml\n[adcs_customtemplates]\n\n; install iis with default website asp upload on 80\n; usage : servers.yml\n[iis]\n;srv01\n\n; install mssql\n; usage : servers.yml\n[mssql]\nsrv02\n; install mssql gui\n; usage : servers.yml\n[mssql_ssms]\nsrv02\n[mssql_reporting]\nsrv02\n\n; install webdav \n[webdav]\n\n; install elk\n; usage : elk.yml\n[elk_server]\nelk\n\n; add log agent for elk\n; usage : elk.yml\n[elk_log]\ndc01\nsrv01\nws01\n\n[laps_dc]\n[laps_server]\n[laps_workstation]\n\n; allow computer update\n; usage : update.yml\n[update]\ndc01\nsrv01\nws01\n\n; disable update\n; usage : update.yml\n[no_update]\n\n; allow defender\n; usage : security.yml\n[defender_on]\ndc01\nsrv01\nsrv02\nws01\n\n; disable defender\n; usage : security.yml\n[defender_off]\n\n[sccm]\nsrv01"
  },
  {
    "path": "ad/SCCM/data/inventory_disable_vagrant",
    "content": "[default]\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=administrator@sccm.lab ansible_password=AZERTY*qsdfg\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01 ansible_user=administrator@sccm.lab ansible_password=AZERTY*qsdfg\nsrv02 ansible_host={{ip_range}}.12 dns_domain=dc01 dict_key=srv02 ansible_user=administrator@sccm.lab ansible_password=AZERTY*qsdfg\nws01 ansible_host={{ip_range}}.13 dns_domain=dc01 dict_key=ws01 ansible_user=administrator@sccm.lab ansible_password=AZERTY*qsdfg\n\n\n[all:vars]\n; domain_name : folder inside ad/\ndomain_name=SCCM\n\n; winrm connection (windows)\nansible_winrm_transport=ntlm\nansible_user=notused\nansible_password=notused\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n\n[domain]\ndc01\nsrv01\nsrv02\nws01"
  },
  {
    "path": "ad/SCCM/providers/aws/inventory",
    "content": "[default]\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=AZERTY*qsdfg\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01 ansible_user=ansible ansible_password=NgtI75cKV+Pu\nsrv02 ansible_host={{ip_range}}.12 dns_domain=dc01 dict_key=srv02 ansible_user=ansible ansible_password=NgtazecKV+Pu\nws01 ansible_host={{ip_range}}.13 dns_domain=dc01 dict_key=ws01 ansible_user=ansible ansible_password=EP+xh7Rk6j90\n\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/SCCM/providers/aws/windows.tf",
    "content": "# t2.medium = 2cpu / 4GB\n# t2.large  = 2cpu / 8GB\n# t2.xlarge = 4cpu / 16GB\n\"dc01\" = {\n  name               = \"dc01\"\n  domain             = \"sccm.lab\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"AZERTY*qsdfg\"\n}\n\"srv01\" = {\n  name               = \"srv01\"\n  domain             = \"sccm.lab\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.11\"\n  password           = \"NgtI75cKV+Pu\"\n}\n\"srv02\" = {\n  name               = \"srv02\"\n  domain             = \"sccm.lab\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.12\"\n  password           = \"NgtazecKV+Pu\"\n}\n\"ws01\" = {\n  name               = \"ws01\"\n  domain             = \"sccm.lab\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.13\"\n  password           = \"EP+xh7Rk6j90\"\n}"
  },
  {
    "path": "ad/SCCM/providers/azure/inventory",
    "content": "[default]\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01 ansible_user=ansible ansible_password=AZERTY*qsdfg\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01 ansible_user=ansible ansible_password=NgtI75cKV+Pu\nsrv02 ansible_host={{ip_range}}.12 dns_domain=dc01 dict_key=srv02 ansible_user=ansible ansible_password=NgtazecKV+Pu\nws01 ansible_host={{ip_range}}.13 dns_domain=dc01 dict_key=ws01 ansible_user=ansible ansible_password=EP+xh7Rk6j90\n\n\n[all:vars]\nadmin_user=goadmin"
  },
  {
    "path": "ad/SCCM/providers/azure/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"dc01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"AZERTY*qsdfg\"\n  size               = \"Standard_B2s\"\n}\n\"srv01\" = {\n  name               = \"srv01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.11\"\n  password           = \"NgtI75cKV+Pu\"\n  size               = \"Standard_B2s\"\n}\n\"srv02\" = {\n  name               = \"srv02\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.12\"\n  password           = \"NgtazecKV+Pu\"\n  size               = \"Standard_B2s\"\n}\n\"ws01\" = {\n  name               = \"ws01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.13\"\n  password           = \"EP+xh7Rk6j90\"\n  size               = \"Standard_B2s\"\n}"
  },
  {
    "path": "ad/SCCM/providers/ludus/config.yml",
    "content": "ludus:\n  - vm_name: \"{{ range_id }}-SCCM-DC\"\n    hostname: \"{{ range_id }}-DC01\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 40\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-SCCM-MECM\"\n    hostname: \"{{ range_id }}-SRV01\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 41\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-SCCM-MSSQL\"\n    hostname: \"{{ range_id }}-SRV02\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 42\n    ram_gb: 4\n    cpus: 4\n    windows:\n      sysprep: true\n  - vm_name: \"{{ range_id }}-SCCM-CLIENT\"\n    hostname: \"{{ range_id }}-WS01\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 43\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n"
  },
  {
    "path": "ad/SCCM/providers/ludus/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sccm.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.40 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.41 dns_domain=dc01 dict_key=srv01\nsrv02 ansible_host={{ip_range}}.42 dns_domain=dc01 dict_key=srv02\nws01 ansible_host={{ip_range}}.43 dns_domain=dc01 dict_key=ws01\n\n[all:vars]\nforce_dns_server=no\ndns_server={{ip_range}}.254\n\ndns_server_forwarder={{ip_range}}.254\n\nansible_user=localuser\nansible_password=password"
  },
  {
    "path": "ad/SCCM/providers/proxmox/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sccm.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.40 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.41 dns_domain=dc01 dict_key=srv01\nsrv02 ansible_host={{ip_range}}.42 dns_domain=dc01 dict_key=srv02\nws01 ansible_host={{ip_range}}.43 dns_domain=dc01 dict_key=ws01\n\n[all:vars]\nforce_dns_server=yes\ndns_server={{ip_range}}.1\n"
  },
  {
    "path": "ad/SCCM/providers/proxmox/windows.tf",
    "content": "\"dc01\" = {\n  name               = \"DC\"\n  desc               = \"DC - windows server 2019 - {{ip_range}}.40\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.40/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"srv01\" = {\n  name               = \"MECM\"\n  desc               = \"SRV01 - MECM - windows server 2019 - {{ip_range}}.41\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.41/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"srv02\" = {\n  name               = \"MSSQL\"\n  desc               = \"SRV02 - MSSQL - windows server 2019 - {{ip_range}}.42\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.42/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n\"ws01\" = {\n  name               = \"CLIENT\"\n  desc               = \"SRV03 - CLIENT - windows server 2019 - {{ip_range}}.43\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"WinServer2019_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.43/24\"\n  gateway            = \"{{ip_range}}.1\"\n}"
  },
  {
    "path": "ad/SCCM/providers/virtualbox/Vagrantfile",
    "content": "boxes = [\n  { :name => \"SCCM-DC\",  :ip => \"{{ip_range}}.10\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n  { :name => \"SCCM-MECM\" , :ip => \"{{ip_range}}.11\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n  { :name => \"SCCM-MSSQL\", :ip => \"{{ip_range}}.12\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n  { :name => \"SCCM-CLIENT\",  :ip => \"{{ip_range}}.13\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n]\n"
  },
  {
    "path": "ad/SCCM/providers/virtualbox/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sccm.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01\nsrv02 ansible_host={{ip_range}}.12 dns_domain=dc01 dict_key=srv02\nws01 ansible_host={{ip_range}}.13 dns_domain=dc01 dict_key=ws01\n"
  },
  {
    "path": "ad/SCCM/providers/vmware/Vagrantfile",
    "content": "boxes = [\n  { :name => \"SCCM-DC\",  :ip => \"{{ip_range}}.10\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n  { :name => \"SCCM-MECM\" , :ip => \"{{ip_range}}.11\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n  { :name => \"SCCM-MSSQL\", :ip => \"{{ip_range}}.12\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n  { :name => \"SCCM-CLIENT\",  :ip => \"{{ip_range}}.13\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n]\n"
  },
  {
    "path": "ad/SCCM/providers/vmware/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sccm.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01\nsrv02 ansible_host={{ip_range}}.12 dns_domain=dc01 dict_key=srv02\nws01 ansible_host={{ip_range}}.13 dns_domain=dc01 dict_key=ws01\n"
  },
  {
    "path": "ad/SCCM/providers/vmware_esxi/Vagrantfile",
    "content": "boxes = [\n  { :name => \"SCCM-DC\",  :ip => \"{{ip_range}}.10\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n  { :name => \"SCCM-MECM\" , :ip => \"{{ip_range}}.11\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n  { :name => \"SCCM-MSSQL\", :ip => \"{{ip_range}}.12\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n  { :name => \"SCCM-CLIENT\",  :ip => \"{{ip_range}}.13\", :box => \"mayfly/windows_server2019\", :cpus => 2, :mem => 4000, :os => \"windows\"},\n]\n"
  },
  {
    "path": "ad/SCCM/providers/vmware_esxi/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\n; ------------------------------------------------\n; sccm.lab\n; ------------------------------------------------\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01\nsrv02 ansible_host={{ip_range}}.12 dns_domain=dc01 dict_key=srv02\nws01 ansible_host={{ip_range}}.13 dns_domain=dc01 dict_key=ws01\n"
  },
  {
    "path": "ad/TEMPLATE/README.md",
    "content": "# Default template\n\nYou can use this template to create your own lab\n\n## Inventory file : Inventory\n\nThis is the ansible inventory file.\n\n- All the vms defined in the vagrant file must be set here.\n- This will do the mapping between IP and the configuration file (data/config.json)\n```\n[default]\ndc01 ansible_host=192.168.56.10 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host=192.168.56.11 dns_domain=dc01 dict_key=srv01\n```\n\n- Vm defined in the inventory must be set into the groups to run the associated roles\n\n## Inventory file : roles\n\n### domain (mandatory)\n- all computers inside domain (mandatory)\n- usage : build.yml, ad-relations.yml, ad-servers.yml, vulnerabilities.yml\n\n### domain controller (mandatory)\n- usage : ad-acl.yml, ad-data.yml, ad-relations.yml, laps.yml\n- all domain controller must be declared here\n\n### server (mandatory if you want servers)\n- domain server to enroll (mandatory if you want servers)\n- usage : ad-data.yml, ad-servers.yml, laps.yml\n\n### parent_dc (mandatory)\n- parent domain controller mandatory even if you don't use child dc\n- usage : ad-servers.yml\n\n### child_dc (optional)\n- child domain controller (need a fqdn child_name.parent_name)\n- usage : ad-servers.yml\n\n### trust (optional)\n- external trust, need domain trust key in config (bidirectionnal)\n- usage : ad-trusts.yml\n\n### adcs (optional)\n- Install adcs\n- usage : adcs.yml\n\n### adcs_customtemplates (optional)\n- install custom templates on the dc\n- usage : adcs.yml\n- by now the template are hardcoded for esc1-4\n\n### iis (optional)\n- install iis with default website asp upload on 80\n- usage : servers.yml\n\n### mssql (optional)\n- install mssql (need the configuration defined in config.json)\n- usage : servers.yml\n\n### mssql_ssms (optional)\n- install mssql gui (does not work on windows server 2016 by default)\n- usage : servers.yml\n\n### webdav (optional)\n- install webdav\n- usage : servers.yml\n\n### elk_server (optional)\n- install elk\n- usage : elk.yml\n- this group is just for the elk linux server\n\n### elk_log (optional)\n- add log agent for elk\n- usage : elk.yml\n- this group is for all windows vm where we want to setup the elk agent\n\n### update (optional)\n- allow computer update (by default yes)\n- usage : update.yml\n\n### no_update (optional)\n- disable computer update\n- usage : update.yml\n\n### defender_on (optional)\n- enable defender (by default defender is enabled on windows)\n- usage : security.yml\n\n### defender_off (optional)\n- disable defender\n- usage : security.yml\n\n## Configuration file : data/config.json\n\n```\n\"lab\" : {\n    \"hosts\" : {\n       # here the hosts configuration\n    },\n    \"domains\" : {\n        # domain configuration\n    }\n```\n\n### Configuration file : hosts\n\nThe host configuration contain one key by host : **the key must match the dict_key in inventory**\n\n- Example : \n```\n    \"hosts\" : {\n        \"dc01\" : {\n            \"hostname\" : \"dctemplate\",\n            \"local_admin_password\": \"dc_and_domain_password\",\n            \"domain\" : \"template.lab\",\n            \"path\" : \"DC=template,DC=lab\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"template\\\\dcadmins\"\n                ]\n            },\n            \"scripts\" : [\"features.ps1\"],\n            \"vulns\" : [\"files\"],\n            \"vulns_vars\" : {\n                \"files\" : {\n                    \"rdp\" : {\n                        \"src\" : \"flag.txt\",\n                        \"dest\" : \"c:\\\\users\\\\administrators\\\\desktop\\\\flag.txt\"\n                    }\n                }\n            }\n        },\n```\n\n- hostname : here put the hostname of the host\n- type : [dc|server] this variable is not read by now but could be used in the future\n- local_admin_password : the administrator password (if the host is a domain controler, this password will be used as the administrator password of the domain)\n- domain : the domain of the host\n- path: the path in the domain\n- local_groups: here you can make local modifications to the vm local groups\n- scripts : if you want to play some custom ps1 scripts present in the scripts/ folder (be carrefull to make script than can be played multiple times in case the provisioning crash and you want to rerun all the steps)\n- vulns : this contains specifics roles presents in ansible/roles/vulns\n- vulns_vars : this contains the variables for the vuln roles you want to run\n- use_laps(optional) : true|false  if you want to use laps on this hosts (servers only)\n- mssql(optional) : if you add the host to the [mssql] role in the inventory, you should add all the mssql special variables (see the mssql part)\n\n#### use_laps (optional, default false)\n\n```\n\"use_laps\": true,\n```\n\n- Define if laps must be deployed on this hosts, value : true or false\n\n#### mssql (for mssql role)\n\n- To install and configure mssql you should add the host where you want it installed in your inventory file :\n\n```\n; install mssql on these hosts\n; usage : servers.yml\n[mssql]\nsrv02\nsrv03\n\n; install mssql gui on these hosts (don't work on windows server 2016)\n; usage : servers.yml\n[mssql_ssms]\nsrv02\n```\n\n- If you add mssql you should add the following variables in the corresponding host in the configuration file, this is mandatory\n\n- Example on srv03\n```\n\"hosts\" : {\n    \"srv03\" : {\n        ...\n        \"mssql\":{\n            \"sa_password\": \"sa_P@ssw0rd!Ess0s\",\n            \"svcaccount\" : \"sql_svc\",\n            \"sysadmins\" : [\n                \"ESSOS\\\\khal.drogo\"\n            ],\n            \"executeaslogin\" : {\n                \"ESSOS\\\\jorah.mormont\" : \"sa\"\n            },\n            \"executeasuser\" : {},\n            \"linked_servers\": {\n                \"CASTELBLACK\" : {\n                    \"data_src\": \"castelblack.north.sevenkingdoms.local\",\n                    \"users_mapping\": [\n                        {\"local_login\": \"ESSOS\\\\khal.drogo\",\"remote_login\": \"sa\", \"remote_password\": \"Sup1_sa_P@ssw0rd!\"}\n                    ]\n                }\n            }\n        }\n```\n\n\n### Configuration file : domains\n\n- The domains part is where you configure your active directory domain\n- You should setup on key for each domain (here template.lab)\n- The key should match the domain key defined on the host part\n\n```\n\"domains\" : {\n    \"template.lab\" : {\n            \"dc\": \"dc01\",\n            \"domain_password\" : \"dc_and_domain_password\",\n            \"netbios_name\": \"TEMPLATE\",\n            \"groups\" : {\n                \"universal\" : {},\n                \"domainlocal\" : {},\n                \"global\" : {\n                    \"admins\" : {\n                        \"managed_by\" : \"alice\",\n                        \"path\" : \"CN=Users,DC=template,DC=lab\"\n                    },\n                    \"srvadmins\" : {\n                        \"managed_by\" : \"bob\",\n                        \"path\" : \"CN=Users,DC=template,DC=lab\"\n                    }\n                }\n            },\n            \"users\" : {\n                \"alice\" : {\n                    \"firstname\"   : \"alice\", \"surname\": \"\",\n                    \"password\"    : \"aupaysdesmerveilles\", \n                    \"description\" : \"\",\n                    \"groups\"      : [\"dcadmins\",\"srvadmins\"],\n                    \"path\"        : \"CN=Users,DC=template,DC=lab\"\n                },\n                \"bob\" : {\n                    \"firstname\"   : \"bob\", \"surname\": \"\",\n                    \"password\"    : \"lebricoleur\",\n                    \"description\" : \"\",\n                    \"groups\"      : [\"srvadmins\"],\n                    \"path\"        : \"CN=Users,DC=template,DC=lab\"\n                }\n            }\n        }\n    }\n```\n\n- dc : this is the matching host key for the primary domain controler\n- domain_password : this must be the same as the administrator password of the primary domain controler\n- netbios_name: the netbios name of the domain\n- groups : here you can define \"universal\",\"global\" or \"domainlocal\" groups\n- users : here you will define all your domain users each key match the user created\n\n#### organisation_units (optional)\n- To add custom organisation units (OU)\n\n- Example on sevenkingdoms.local :\n```\n\"domains\" : {\n    \"sevenkingdoms.local\" : {\n            ...\n            \"organisation_units\" : {\n                \"Vale\"        : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"IronIslands\" : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Riverlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Crownlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Stormlands\"  : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Westerlands\" : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Reach\"       : { \"path\" : \"DC=sevenkingdoms,DC=local\"},\n                \"Dorne\"       : { \"path\" : \"DC=sevenkingdoms,DC=local\"}\n            },\n```\n\n#### multi_domain_groups_member (optional)\n- Add a user from another domain into a group (must be a domainlocal group)\n\n- Example on sevenkingdoms.local :\n\n```\n\"domains\" : {\n    \"sevenkingdoms.local\" : {\n            ...\n            \"groups\" : {\n                ...\n                \"domainlocal\" : {\n                    \"AcrossTheSea\" : {\n                        \"path\" : \"CN=Users,DC=North,DC=sevenkingdoms,DC=local\"\n                    }\n                }\n            },\n            \"multi_domain_groups_member\" : {\n                \"AcrossTheSea\" : [\n                    \"essos.local\\\\daenerys.targaryen\"\n                ]\n            },\n```\n\n#### acls (optional)\n- To create ace relations in your active directory\n\n- Example on sevenkingdoms.local\n```\n\"domains\" : {\n    \"sevenkingdoms.local\" : {\n        ...\n        \"acls\" : {\n            \"GenericAll_khal_viserys\" : {\"for\": \"khal.drogo\", \"to\": \"viserys.targaryen\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n            \"GenericAll_spy_jorah\" : {\"for\": \"Spys\", \"to\": \"jorah.mormont\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n            \"GenericAll_khal_esc4\" : {\"for\": \"khal.drogo\", \"to\": \"CN=ESC4,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local\", \"right\": \"GenericAll\", \"inheritance\": \"None\"},\n            \"WriteProperty_petyer_domadmin\" : {\"for\": \"viserys.targaryen\", \"to\": \"jorah.mormont\", \"right\": \"WriteProperty\", \"inheritance\": \"All\"},\n            \"GenericWrite_DragonsFriends_braavos\" : {\"for\": \"DragonsFriends\", \"to\": \"braavoos$\", \"right\": \"GenericWrite\", \"inheritance\": \"None\"}\n        },\n```\n\n- acl are in the following format : \n  - for : the user concerned (user or group name)\n  - to  : the user or group or CN target (where the ace will be applied)\n  - right : the right to apply on this list :\n    - AccessSystemSecurity\n    - CreateChild\n    - Delete\n    - DeleteChild\n    - DeleteTree\n    - ExtendedRight\n    - GenericAll\n    - GenericExecute\n    - GenericRead\n    - GenericWrite\n    - ListChildren\n    - ListObject\n    - ReadControl\n    - ReadProperty\n    - Self\n    - Synchronize\n    - WriteDacl\n    - WriteOwner\n    - WriteProperty\n  - right can also be extended right, the extended right allowed are:\n    - Ext-User-Force-Change-Password\n    - Ext-Write-Self-Membership\n    - Ext-Self-Self-Membership\n  - inheritance: enable inheritance (All or None)\n\n\n- To add anonymous rpc just add on the dc (this will allow anonymous user listing ):\n\n```\n\"acls\" : {\n    \"anonymous_rpc\" : {\"for\": \"NT AUTHORITY\\\\ANONYMOUS LOGON\", \"to\": \"DC=North,DC=sevenkingdoms,DC=local\", \"right\": \"ReadProperty\", \"inheritance\": \"All\"},\n    \"anonymous_rpc2\" : {\"for\": \"NT AUTHORITY\\\\ANONYMOUS LOGON\", \"to\": \"DC=North,DC=sevenkingdoms,DC=local\", \"right\": \"GenericExecute\", \"inheritance\": \"All\"}\n},\n```\n\n#### laps_path and laps_readers (optional)\n\n- To add laps just add laps_path on your domain with the name of the OU to create.\n- all hosts with use_laps : true will be moved to that OU and laps will be applied\n- laps_readers list all the users and group allow to read the laps password\n\n```\n\"domains\" : {\n    \"north.sevenkingdoms.local\" : {\n        ...\n        \"laps_path\": \"OU=Laps,DC=north,DC=sevenkingdoms,DC=local\",\n        ...\n        \"laps_readers\": [\n                \"jorah.mormont\",\n                \"Spys\"\n            ],\n        ...\n    }\n}\n```\n\n#### trust (for trusts role)\n\n- In case of external trust trust key must be setup in each domains\n```\n    \"domains\" : {\n        \"sevenkingdoms.local\" : {\n            ...\n            \"trust\" : \"essos.local\",\n            ...\n        },\n        \"essos.local\" : {\n            ...\n            \"trust\" : \"sevenkingdoms.local\",\n```\n\n#### ca_server (for adcs_customtemplates role)\n- This param is use to precise the host to use on the template creation, this is mandatory if [adcs_customtemplates] role is used\n\n```\n   \"domains\" : {\n        \"essos.local\" : {\n            ...\n            \"ca_server\": \"Braavos\",\n```"
  },
  {
    "path": "ad/TEMPLATE/data/config.json",
    "content": "{\n\"lab\" : {\n    \"hosts\" : {\n        \"dc01\" : {\n            \"hostname\" : \"dctemplate\",\n            \"type\" : \"dc\",\n            \"local_admin_password\": \"dc_and_domain_password\",\n            \"domain\" : \"template.lab\",\n            \"path\" : \"DC=template,DC=lab\",\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"template\\\\dcadmins\"\n                ]\n            },\n            \"scripts\" : [\"features.ps1\"],\n            \"vulns\" : [\"files\"],\n            \"vulns_vars\" : {\n                \"files\" : {\n                    \"rdp\" : {\n                        \"src\" : \"flag.txt\",\n                        \"dest\" : \"c:\\\\users\\\\administrators\\\\desktop\\\\flag.txt\"\n                    }\n                }\n            }\n        },\n        \"srv01\" : {\n            \"hostname\" : \"srvtemplate\",\n            \"type\" : \"server\",\n            \"local_admin_password\": \"srv_password\",\n            \"domain\" : \"template.lab\",\n            \"path\" : \"DC=template,DC=lab\",\n            \"use_laps\": true,\n            \"local_groups\" : {\n                \"Administrators\" : [\n                    \"template\\\\dcadmins\",\n                    \"template\\\\srvadmins\"\n                ],\n                \"Remote Desktop Users\" : [\n                    \"template\\\\srvadmins\"\n                ]\n            },\n            \"vulns\" : [\"openshares\"]\n        }\n    },\n    \"domains\" : {\n        \"template.lab\" : {\n            \"dc\": \"dc01\",\n            \"domain_password\" : \"dc_and_domain_password\",\n            \"netbios_name\": \"TEMPLATE\",\n            \"groups\" : {\n                \"global\" : {\n                    \"dcadmins\" : {\n                        \"managed_by\" : \"alice\",\n                        \"path\" : \"CN=Users,DC=template,DC=lab\"\n                    },\n                    \"srvadmins\" : {\n                        \"managed_by\" : \"bob\",\n                        \"path\" : \"CN=Users,DC=template,DC=lab\"\n                    }\n                }\n            },\n            \"users\" : {\n                \"alice\" : {\n                    \"firstname\"   : \"alice\", \"surname\": \"\",\n                    \"password\"    : \"aupaysdesmerveilles\", \n                    \"description\" : \"\",\n                    \"groups\"      : [\"dcadmins\",\"srvadmins\"],\n                    \"path\"        : \"CN=Users,DC=template,DC=lab\"\n                },\n                \"bob\" : {\n                    \"firstname\"   : \"bob\", \"surname\": \"\",\n                    \"password\"    : \"lebricoleur\",\n                    \"description\" : \"\",\n                    \"groups\"      : [\"srvadmins\"],\n                    \"path\"        : \"CN=Users,DC=template,DC=lab\"\n                }\n            }\n        }\n    }\n}\n}\n"
  },
  {
    "path": "ad/TEMPLATE/data/inventory",
    "content": "; GLOBAL CONFIG\n[all:vars]\n; domain_name : folder inside ad/\ndomain_name=TEMPLATE\n\n; global settings inventory default value\nkeyboard_layouts=[\"en-US\", \"da-DK\", \"fr-FR\"]\n\n; modify this to add a default route\nadd_route=no\nroute_gateway=192.168.56.1\nroute_network=10.0.0.0/8\n\n; modify this to enable http proxy\nenable_http_proxy=no\nad_http_proxy=http://x.x.x.x:xxxx\nad_https_proxy=http://x.x.x.x:xxxx\n\n;force_dns_server\nforce_dns_server=no\ndns_server=1.1.1.1\n\n; winrm connection (windows)\nansible_user=vagrant\nansible_password=vagrant\nansible_connection=winrm\nansible_winrm_server_cert_validation=ignore\nansible_winrm_operation_timeout_sec=400\nansible_winrm_read_timeout_sec=500\n# ansible_winrm_transport=basic\n# ansible_port=5985\n\n; proxy settings (the lab need internet for some install, if you are behind a proxy you should set the proxy here)\nenable_http_proxy=no\nad_http_proxy=http://x.x.x.x:xxxx\nad_https_proxy=http://x.x.x.x:xxxx\n\n; LAB SCENARIO CONFIGURATION -----------------------------\n\n; computers inside domain (mandatory)\n; usage : build.yml, ad-relations.yml, ad-servers.yml, vulnerabilities.yml\n[domain]\ndc01\nsrv01\n\n; domain controler (mandatory)\n; usage : ad-acl.yml, ad-data.yml, ad-relations.yml, laps.yml\n[dc]\ndc01\n\n; domain server to enroll (mandatory if you want servers)\n; usage : ad-data.yml, ad-servers.yml, laps.yml\n[server]\nsrv01\n\n; workstation to enroll (mandatory if you want workstation)\n; usage : ad-servers.yml, laps.yml\n[workstation]\n\n; parent domain controler (mandatory)\n; usage : ad-servers.yml\n[parent_dc]\ndc01\n\n; child domain controler (need a fqdn child_name.parent_name)\n; usage : ad-servers.yml\n[child_dc]\n; external trust, need domain trust key in config (bidirectionnal)\n; usage : ad-trusts.yml\n[trust]\n; install adcs\n; usage : adcs.yml\n[adcs]\ndc01\n; install custom template (dc)\n; usage : adcs.yml\n[adcs_customtemplates]\n; install iis with default website asp upload on 80\n; usage : servers.yml\n[iis]\n; install mssql\n; usage : servers.yml\n[mssql]\n; install mssql gui\n; usage : servers.yml\n[mssql_ssms]\n; install webdav \n[webdav]\n; install elk\n; usage : elk.yml\n[elk_server]\n; add log agent for elk\n; usage : elk.yml\n[elk_log]\n;activate laps\n;usage laps.yml\n[laps_dc]\n;laps servers\n;usage laps.yml\n[laps_server]\n;laps workstation\n;usage laps.yml\n[laps_workstation]\n; allow computer update\n; usage : update.yml\n[update]\n; disable update\n; usage : update.yml\n[no_update]\ndc01\nsrv01\n; allow defender\n; usage : security.yml\n[defender_on]\n; disable defender\n; usage : security.yml\n[defender_off]\ndc01\nsrv01\n"
  },
  {
    "path": "ad/TEMPLATE/files/flag.txt",
    "content": "flag"
  },
  {
    "path": "ad/TEMPLATE/providers/virtualbox/Vagrantfile",
    "content": "boxes = [\n  { :name => \"DC01\",  :ip => \"192.168.56.30\", :box => \"jborean93/WindowsServer2019\", :os => \"windows\", :cpus => 2, :mem => 4000},\n  { :name => \"SRV01\", :ip => \"192.168.56.31\", :box => \"jborean93/WindowsServer2019\", :os => \"windows\", :cpus => 2, :mem => 4000}\n]\n\n  # Recommended boxes\n  # Windows server 2019 (180days)\n  #{ :name => \"X\", :ip => \"192.168.56.x\", :box => \"jborean93/WindowsServer2019\", :os => \"windows\"},\n  #{ :name => \"X\", :ip => \"192.168.56.x\", :box => \"StefanScherer/windows_2019\", :box_version => \"2021.05.15\", :os => \"windows\"},\n  #{ :name => \"X\", :ip => \"192.168.56.x\", :box => \"StefanScherer/windows_2019\", :box_version => \"2020.07.17\", :os => \"windows\"},\n  # Windows server 2016 (180days)\n  #{ :name => \"X\", :ip => \"192.168.56.x\", :box => \"StefanScherer/windows_2016\", :box_version => \"2017.12.14\", :os => \"windows\"},\n  #{ :name => \"X\", :ip => \"192.168.56.x\", :box => \"StefanScherer/windows_2016\", :box_version => \"2019.02.14\", :os => \"windows\"},\n  # Windows 10 (90days)\n  # TODO\n"
  },
  {
    "path": "ad/TEMPLATE/providers/virtualbox/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01\n"
  },
  {
    "path": "ad/TEMPLATE/providers/vmware/Vagrantfile",
    "content": "boxes = [\n  { :name => \"DC01\",  :ip => \"192.168.56.30\", :box => \"jborean93/WindowsServer2019\", :os => \"windows\", :cpus => 2, :mem => 4000},\n  { :name => \"SRV01\", :ip => \"192.168.56.31\", :box => \"jborean93/WindowsServer2019\", :os => \"windows\", :cpus => 2, :mem => 4000}\n]"
  },
  {
    "path": "ad/TEMPLATE/providers/vmware/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01\n"
  },
  {
    "path": "ad/TEMPLATE/providers/vmware_esxi/Vagrantfile",
    "content": "boxes = [\n  { :name => \"DC01\",  :ip => \"192.168.56.30\", :box => \"jborean93/WindowsServer2019\", :os => \"windows\", :cpus => 2, :mem => 4000},\n  { :name => \"SRV01\", :ip => \"192.168.56.31\", :box => \"jborean93/WindowsServer2019\", :os => \"windows\", :cpus => 2, :mem => 4000}\n]"
  },
  {
    "path": "ad/TEMPLATE/providers/vmware_esxi/inventory",
    "content": "[default]\n; Note: ansible_host *MUST* be an IPv4 address or setting things like DNS\n; servers will break.\ndc01 ansible_host={{ip_range}}.10 dns_domain=dc01 dict_key=dc01\nsrv01 ansible_host={{ip_range}}.11 dns_domain=dc01 dict_key=srv01\n"
  },
  {
    "path": "ad/TEMPLATE/scripts/features.ps1",
    "content": "# add you lab features in PS"
  },
  {
    "path": "ansible/ad-acl.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# set AD datas ==================================================================================================\n\n- name: ACL inside AD\n  hosts: dc\n  roles:\n  - { role: 'acl', tags: 'acl'}\n  vars:\n    ad_acls: \"{{lab.domains[lab.hosts[dict_key].domain].acls | default({})}}\"\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\""
  },
  {
    "path": "ansible/ad-child_domain.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# set AD datas ==================================================================================================\n\n# child\n- name: Child DC AD configuration\n  hosts: child_dc\n  roles:\n    - { role: 'child_domain', tags: 'child_domain'}\n    - { role: 'dns_conditional_forwarder', tags: 'dns_conditional_forwarder' }\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    netbios_name: \"{{lab.domains[domain].netbios_name}}\"\n    parent_domain: \"{{'.'.join(domain.split('.')[1:])}}\"\n    parent_domain_user: \"{{admin_user}}@{{parent_domain}}\"\n    parent_domain_password: \"{{lab.domains[parent_domain].domain_password}}\"\n    source_dc: \"{{lab.hosts[lab.domains[parent_domain].dc].hostname}}.{{parent_domain}}\"\n    zone_name: \"{{parent_domain}}\"\n    remote_dc: \"{{lab.domains[parent_domain].dc}}\"\n    master_server: \"{{hostvars[remote_dc].ansible_host}}\"\n    replication: \"none\"\n\n# parent add DNS value of child DC\n- name: Parent DC ADD DNS configuration\n  hosts: parent_dc\n  roles:\n    - { role: 'parent_child_dns', tags: 'parent_child_dns'}\n  vars:\n    lab: \"{{lab}}\"\n    domains: \"{{lab.domains.keys()}}\"\n    domain: \"{{lab.hosts[dict_key].domain}}\""
  },
  {
    "path": "ansible/ad-data.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# set AD datas ==================================================================================================\n- name: DCs AD data configuration\n  hosts: dc\n  roles:\n    - { role: 'password_policy', tags: 'policy', try_before_lock: \"5\", pass_length: \"5\", lock_duration: \"00:05:00\", lock_observation: \"00:05:00\", complexity: false}\n    - { role: 'ad', tags: 'ad_domain_data' }\n  vars:\n    hostname: \"{{lab.hosts[dict_key].hostname}}\"\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    domain_server: \"{{lab.hosts[dict_key].hostname}}.{{domain}}\"\n    ad_users: \"{{lab.domains[lab.hosts[dict_key].domain].users}}\"\n    ad_ou: \"{{lab.domains[lab.hosts[dict_key].domain].organisation_units  | default({}) }}\"\n    ad_groups: \"{{lab.domains[lab.hosts[dict_key].domain].groups}}\"\n\n- name: \"Servers AD data configuration\"\n  hosts: server\n  roles:\n    - { role: 'settings/copy_files', tags: 'download_files' }\n  vars:\n    hostname: \"{{lab.hosts[dict_key].hostname}}\"\n    domain_ou_path: \"{{lab.hosts[dict_key].path}}\"\n\n- name: \"Move to OU\"\n  hosts: dc\n  roles:\n    - { role: 'move_to_ou', tags: 'move_to_ou'}\n  vars:\n    hosts_dict: \"{{lab.hosts}}\"\n    member_domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_password: \"{{lab.domains[member_domain].domain_password}}\""
  },
  {
    "path": "ansible/ad-enroll_linux.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n\n- name: Enroll linux machine to domain\n  hosts: linux_domain\n  become: yes\n  roles:\n  - { role: 'linux/add_linux_to_domain', tags: 'linux_domain'}\n  vars:\n    hostname: \"{{lab.hosts[dict_key].hostname}}\"\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    dc_key: \"{{lab.domains[domain].dc}}\"\n    dc_name: \"{{lab.hosts[dc_key].hostname}}\"\n    dc_fqdn: \"{{dc_name}}.{{domain}}\"\n    dc_ip: \"{{hostvars[dc_key].ansible_host}}\"\n    domain_username: \"{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    sudoers_group: \"{{lab.hosts[dict_key].local_groups.sudoers | default([])}}\"\n    ssh_group: \"{{lab.hosts[dict_key].local_groups.ssh | default([])}}\"\n\n- name: Setup DNS records for linux machines on all domain controllers\n  hosts: dc\n  tasks:\n    - name: Add DNS record for each linux_domain machine\n      include_role:\n        name: add_dns_record\n      vars:\n        domain: \"{{ lab.hosts[item].domain }}\"\n        record_name: \"{{ lab.hosts[item].hostname }}\"\n        record_type: \"A\"\n        record_value: \"{{ hostvars[item].ansible_host }}\"\n      loop: \"{{ groups['linux_domain'] }}\"\n      loop_control:\n        loop_var: item"
  },
  {
    "path": "ansible/ad-gmsa.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# set AD datas ==================================================================================================\n\n- name: GMSA inside AD\n  hosts: dc\n  roles:\n  - { role: 'gmsa', tags: 'gmsa'}\n  vars:\n    ad_gmsa: \"{{lab.domains[lab.hosts[dict_key].domain].gmsa | default({})}}\"\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n\n- name: GMSA hosts\n  hosts: server, workstation\n  roles:\n  - { role: 'gmsa_hosts', tags: 'gmsa'}\n  vars:\n    ad_gmsa: \"{{lab.domains[lab.hosts[dict_key].domain].gmsa | default({})}}\"\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    hostname: \"{{lab.hosts[dict_key].hostname}}\"\n"
  },
  {
    "path": "ansible/ad-members.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# set AD datas ==================================================================================================\n- name: \"play servers AD configuration\"\n  hosts: server\n  roles:\n    - { role: 'member_server', tags: 'server'}\n  vars:\n    member_domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{admin_user}}@{{member_domain}}\"\n    domain_password: \"{{lab.domains[member_domain].domain_password}}\"\n\n- name: \"play workstations AD configuration\"\n  hosts: workstation\n  roles:\n    - { role: 'commonwkstn', tags: 'workstation'}\n  vars:\n    member_domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{admin_user}}@{{member_domain}}\"\n    domain_password: \"{{lab.domains[member_domain].domain_password}}\""
  },
  {
    "path": "ansible/ad-parent_domain.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# set AD datas ==================================================================================================\n\n# parent controlers\n- name: Main DC AD configuration\n  hosts: parent_dc\n  roles:\n  - { role: 'domain_controller', tags: 'dc_main_domains' }\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{admin_user}}@{{domain}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    netbios_name: \"{{lab.domains[domain].netbios_name}}\"\n"
  },
  {
    "path": "ansible/ad-relations.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# set AD datas ==================================================================================================\n\n- name: \"Adjust rights configuration\"\n  hosts: domain\n  roles:\n    - { role: \"settings/adjust_rights\", tags: 'adjust_rights'}\n    - { role: \"settings/user_rights\", tags: 'adjust_rights'}\n  vars:\n    local_groups: \"{{lab.hosts[dict_key].local_groups  | default({}) }}\"\n\n\n# doesen't work see : https://github.com/ansible-collections/community.windows/blob/main/plugins/modules/win_domain_group_membership.ps1\n# ligne 62 : use the given credentials to distant domain -> wrong\n- name: cross domain groups\n  hosts: dc\n  roles:\n  - { role: 'groups_domains', tags: 'groups_domains'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_server: \"{{lab.hosts[dict_key].hostname}}.{{domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    domain_groups_members: \"{{lab.domains[domain].multi_domain_groups_member | default({}) }}\"\n"
  },
  {
    "path": "ansible/ad-servers.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# set AD datas ==================================================================================================\n\n- name: Prepare servers set admin password, set hostname\n  hosts: domain\n  tags: 'prepare_servers'\n  roles:\n  - { role: 'settings/admin_password', tags: 'admin_password' }\n  - { role: 'settings/hostname', tags: 'hostname' }\n  vars:\n    local_admin_password: \"{{lab.hosts[dict_key].local_admin_password}}\"\n    hostname: \"{{lab.hosts[dict_key].hostname}}\"\n"
  },
  {
    "path": "ansible/ad-trusts.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n# set AD trusts ==================================================================================================\n\n- name: Trusts configuration prepare\n  hosts: trust\n  roles:\n  - { role: 'settings/disable_nat_adapter' , tags: 'disable_nat_adapter'}\n  - { role: 'dns_conditional_forwarder', tags: 'dns_conditional_forwarder' }\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    remote_forest: \"{{lab.domains[domain].trust}}\"\n    zone_name: \"{{remote_forest}}\"\n    remote_dc: \"{{lab.domains[remote_forest].dc}}\"\n    master_server: \"{{hostvars[remote_dc].ansible_host}}\"\n    replication: \"forest\"\n\n- name: Trusts configuration\n  hosts: trust\n  serial: 1 # add one trust at a time to avoid issues\n  roles:\n  - { role: 'trusts', tags: 'trust' }\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    remote_forest: \"{{lab.domains[domain].trust}}\"\n    remote_admin: \"Administrator@{{remote_forest}}\"\n    remote_admin_password: \"{{lab.domains[remote_forest].domain_password}}\"\n    zone_name: \"{{remote_forest}}\"\n    remote_dc: \"{{lab.domains[remote_forest].dc}}\"\n    master_server: \"{{hostvars[remote_dc].ansible_host}}\"\n\n- name: Trusts configuration end\n  hosts: trust\n  roles:\n  - { role: 'settings/enable_nat_adapter', tags: 'enable_nat_adapter'}\n\n\n# add DNS conditional forwarder on all trust dc for each other subdomains\n- name: Adjust DNS conditional forwarded configuration\n  hosts: trust\n  roles:\n  - { role: 'dc_dns_conditional_forwarder', tags: 'dns_conditional_forwarder' }\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    replication: \"forest\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    parent_domain: \"{{'.'.join(domain.split('.')[1:]) | default('')}}\"\n    trust: \"{{lab.domains[domain].trust | default('')}}\"\n    lab: \"{{lab}}\"\n    domains: \"{{lab.domains.keys()}}\"\n"
  },
  {
    "path": "ansible/ad.yml",
    "content": "# create main domains, child domain and enroll servers\n- import_playbook: ad-servers.yml\n# create the trust relationships\n- import_playbook: ad-trusts.yml\n# import the ad datas : users/groups...\n- import_playbook: ad-data.yml\n# set the rights and the group domains relations\n- import_playbook: ad-relations.yml\n# Add adcs\n- import_playbook: adcs.yml\n# set the ACL\n- import_playbook: ad-acl.yml"
  },
  {
    "path": "ansible/adcs.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n# set AD datas ==================================================================================================\n\n- name: ADCS\n  hosts: adcs\n  roles:\n  - { role: 'adcs', tags: 'adcs'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    ca_common_name: \"{{lab.domains[domain].netbios_name}}-CA\"\n    ca_web_enrollment: \"{{lab.domains[domain].ca_web_enrollment | default(true)}}\"\n\n- name: ADCS\n  hosts: adcs_customtemplates\n  roles:\n  - { role: 'adcs_templates', tags: 'adcs_templates'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    ca_common_name: \"{{lab.domains[domain].netbios_name}}-CA\"\n    ca_host: \"{{lab.domains[domain].ca_server}}\"\n"
  },
  {
    "path": "ansible/ansible.cfg",
    "content": "[defaults]\nhost_key_checking     = false\ndisplay_skipped_hosts = false\nshow_per_host_start   = True\ndeprecation_warning   = false\n;stdout_callback         = yaml"
  },
  {
    "path": "ansible/build.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n- name: build all\n  hosts: domain\n  roles:\n    - { role: 'common', tags: 'common', http_proxy: \"{{enable_http_proxy}}\"}\n    - { role: 'settings/keyboard', tags: 'keyboard', layouts: \"{{keyboard_layouts}}\" }\n\n# do not add srv with no update -> generate error on iis install\n- name: build all no update\n  hosts: no_update\n  roles:\n    - { role: 'settings/no_updates', tags: 'no_updates' }\n\n\n- name: \"Launch windows updates before continue\"\n  hosts: update\n  roles:\n    - { role: 'settings/updates', tags: 'updates'}"
  },
  {
    "path": "ansible/data.yml",
    "content": "---\n- name: \"Read data files\"\n  hosts: domain:linux_domain:extensions\n  connection: local\n  vars_files:\n    - \"{{data_path}}/config.json\"\n  tasks:\n    - name: save the Json data to a Variable as a Fact\n      set_fact:\n        lab: \"{{lab}}\"\n        cacheable: yes\n      run_once: true\n\n    - name: find domain_adapter\n      set_fact:\n       domain_adapter=\"{{item.connection_name}}\"\n      when: item.ipv4.address == hostvars[dict_key].ansible_host\n      with_items: \"{{ ansible_interfaces }}\"\n      run_once: true\n\n    - name: find nat_adapter\n      set_fact:\n       nat_adapter=\"{{item.connection_name}}\"\n      when: item.ipv4.address != hostvars[dict_key].ansible_host\n      with_items: \"{{ ansible_interfaces }}\"\n      run_once: true\n\n    - name: find number of interfaces\n      set_fact:\n       number_of_interfaces=\"{{ansible_interfaces|length}}\"\n      run_once: true\n\n    - name: find if two adapters\n      set_fact:\n       two_adapters=\"{{ 'yes' if number_of_interfaces != '1' else 'no' }}\"\n      run_once: true\n\n    - name: confirm nat_adapter\n      set_fact:\n       nat_adapter=\"{{domain_adapter}}\"\n      when: not two_adapters\n      run_once: true\n\n#    - debug:\n#        msg: \"domain interface : {{domain_adapter}}\"\n#    - debug:\n#        msg: \"number_of_interfaces : {{number_of_interfaces}}\"\n#    - debug:\n#        msg: \"two_adapters : {{two_adapters}}\"\n#    - debug:\n#        msg: \"nat interface : {{nat_adapter}}\"\n"
  },
  {
    "path": "ansible/dhcp.yml",
    "content": "- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n- name: \"Setup Prerequisites\"\n  hosts: dc\n  roles:\n    - { role: 'dhcp', tags: 'dhcp_install'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    sccm_server: \"{{lab.domains[domain].sccm.sccm_server | default('')}}\"\n    dc_key: \"{{lab.domains[domain].dc}}\"\n    dc_name: \"{{lab.hosts[dc_key].hostname}}\"\n    dc_fqdn: \"{{dc_name}}.{{domain}}\"\n    dc_ip: \"{{hostvars[dc_key].ansible_host}}\"\n    ip_root: \"{{'.'.join(dc_ip.split('.')[:3])}}\"\n    ip_from: \"{{ip_root}}.150\"\n    ip_to: \"{{ip_root}}.200\"\n    ip_mask: \"255.255.255.0\"\n    lease_duration: \"1.00:00:00\"\n    dns_ip: \"{{dc_ip}}\"\n"
  },
  {
    "path": "ansible/disable_vagrant.yml",
    "content": "---\n- name: \"Disable vagrant\"\n  hosts: domain\n  roles:\n    - { role: 'disable_user', tags: 'disable_vagrant', username: \"vagrant\"}\n\n- name: \"Disable vagrant\"\n  hosts: linux_domain\n  become: yes\n  roles:\n    - { role: 'linux/disable_user', tags: 'disable_vagrant', username: \"vagrant\"}"
  },
  {
    "path": "ansible/elk.yml",
    "content": "# LOGS and Monitoring ==========================================================================================\n- name: Install ELK\n  hosts: elk_server\n  become: yes\n  roles:\n    - { role: 'elk', tags: 'elk' }\n\n- name: Install log agent on windows vms\n  hosts: elk_log\n  roles:\n    - { role: 'logs_windows', tags: 'agent' }"
  },
  {
    "path": "ansible/enable_vagrant.yml",
    "content": "---\n- name: \"Enable vagrant\"\n  hosts: domain\n  roles:\n    - { role: 'enable_user', tags: 'enable_vagrant', username: \"vagrant\"}\n\n- name: \"Disable vagrant\"\n  hosts: linux_domain\n  become: yes\n  roles:\n    - { role: 'linux/enable_user', tags: 'enable_user', username: \"vagrant\"}"
  },
  {
    "path": "ansible/fix_dns.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n- name: setup dns again on all domain computers\n  hosts: domain\n  roles:\n    - { role: 'fix_dns', tags: 'fix_dns' }"
  },
  {
    "path": "ansible/fix_trust.yml",
    "content": "---\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n\n# use this to change machine password if the trust between the dc and the computer is broken\n- name: Fix trust relationship between this workstation and the primary domain failed\n  hosts: srv02,srv03\n  tasks:\n    - name: reset machine password\n      ansible.windows.win_powershell:\n        script: |\n          [CmdletBinding()]\n          param (\n              [String]\n              $domain_username,\n\n              [String]\n              $domain_password\n          )\n          $pass = ConvertTo-SecureString $domain_password -AsPlainText -Force\n          $Cred = New-Object System.Management.Automation.PSCredential ($domain_username, $pass)\n          Reset-ComputerMachinePassword -Credential $Cred\n        error_action: stop\n        parameters:\n          domain_username: \"{{lab.hosts[dict_key].domain}}\\\\Administrator\"\n          domain_password: \"{{lab.domains[lab.hosts[dict_key].domain].domain_password}}\"\n\n    - name: \"Reboot and wait for the AD system to restart\"\n      win_reboot:\n        test_command: \"Get-ADUser -Identity Administrator -Properties *\"\n"
  },
  {
    "path": "ansible/glpi.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n\n- name: Install GLPI\n  hosts: glpi\n  gather_facts: false\n  become: yes\n  roles:\n  - { role: 'linux/common', tags: 'linux_common'}\n  - { role: 'linux/apache', tags: 'linux_apache'}\n  - { role: 'linux/php', tags: 'linux_php'}\n  - { role: 'geerlingguy.mysql', tags: 'mysql'}\n  - { role: 'linux/glpi', tags: 'glpi'}\n  vars:\n    mysql_root_password: mysuperR00Tpassword\n    mysql_root_password_update: true\n    mysql_databases:\n      - name: glpi\n        encoding: utf8\n        collation: utf8_general_ci\n    mysql_users:\n      - name: glpi\n        host: \"%\"\n        password: glpi\n        priv: \"glpi.*:ALL\"\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    dc_key: \"{{lab.domains[domain].dc}}\"\n    dc_name: \"{{lab.hosts[dc_key].hostname}}\"\n    dc_fqdn: \"{{dc_name}}.{{domain}}\"\n    glpi_ldap:\n      name: \"Active_Directory-ldap-{{lab.hosts[dict_key].domain}}\"\n      host: \"{{dc_fqdn}}\"\n      basedn: \"{{lab.hosts[dc_key].path}}\"\n      rootdn: \"CN=sunfyre,CN=Users,{{lab.hosts[dc_key].path}}\"\n      port: 636\n      glpi_user_password: \"BSno5DP4tjJ4jIu8is3B\"\n    glpi_local_users_pass: \"glPwnM33FTW!\"\n"
  },
  {
    "path": "ansible/interfaces.yml",
    "content": "---\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n#- name: show variables\n#  hosts: domain\n#  tasks:\n#    - debug:\n#        \"var=ansible_interfaces\"\n\n- name: set Network adapter variables\n  hosts: domain\n  tasks:\n     - set_fact:\n         domain_adapter=\"{{item.connection_name}}\"\n       when: item.ipv4.address == hostvars[dict_key].ansible_host\n       with_items: \"{{ ansible_interfaces }}\"\n     - set_fact:\n         nat_adapter=\"{{item.connection_name}}\"\n       when: item.ipv4.address != hostvars[dict_key].ansible_host\n       with_items: \"{{ ansible_interfaces }}\"\n     - set_fact:\n         number_of_interfaces=\"{{ansible_interfaces|length}}\"\n     - set_fact:\n         two_adapters=\"{{ 'no' if number_of_interfaces != '1' else 'yes' }}\"\n     - set_fact:\n         nat_adapter=\"{{domain_adapter}}\"\n       when: two_adapters == 'no'\n\n- name: show variables\n  hosts: domain\n  tasks:\n    - debug:\n        msg: \"domain interface : {{domain_adapter}}\"\n    - debug:\n        msg: \"nat interface : {{nat_adapter}}\"\n    - debug:\n        msg: \"two_adapters : {{two_adapters}}\"\n"
  },
  {
    "path": "ansible/keepass.yml",
    "content": "- name: Install keepass\n  hosts: keepass\n  roles:\n    - { role: 'keepass', tags: 'keepass' }"
  },
  {
    "path": "ansible/klink.yml",
    "content": "- name: Install klink\n  hosts: klink\n  roles:\n    - { role: 'klink', tags: 'klink' }"
  },
  {
    "path": "ansible/laps.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n- name: configure laps on DCs\n  hosts: laps_dc\n  roles:\n    - { role: 'laps/dc', tags: 'laps-dc'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    laps_path: \"{{lab.domains[domain].laps_path if lab.domains[domain].laps_path is defined else false}}\"\n    hosts_dict: \"{{lab.hosts}}\"\n\n- name: configure laps on servers\n  hosts: laps_server, laps_workstation\n  roles:\n    - { role: 'laps/server', tags: 'laps-server'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    laps_path: \"{{lab.domains[domain].laps_path if lab.domains[domain].laps_path is defined else false}}\"\n    use_laps: \"{{lab.hosts[dict_key].use_laps if lab.hosts[dict_key].use_laps is defined else false}}\"\n\n\n- name: verify and show laps passwords\n  hosts: laps_dc\n  roles:\n    - { role: 'laps/verify', tags: 'laps-verify'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    laps_path: \"{{lab.domains[domain].laps_path if lab.domains[domain].laps_path is defined else false}}\"\n    hosts_dict: \"{{lab.hosts}}\"\n\n- name: set laps users and groups permission\n  hosts: laps_dc\n  roles:\n    - { role: 'laps/permissions', tags: 'laps-permissions'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    laps_path: \"{{lab.domains[domain].laps_path if lab.domains[domain].laps_path is defined else false}}\"\n    laps_readers: \"{{lab.domains[domain].laps_readers  | default([]) }}\"\n"
  },
  {
    "path": "ansible/localusers.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# set local users ==================================================================================================\n- name: Local Users\n  hosts: domain\n  roles:\n    - { role: 'localusers', tags: 'localusers' }\n  vars:\n    local_users: \"{{ lab.hosts[dict_key].local_users | default({}) }}\""
  },
  {
    "path": "ansible/main.yml",
    "content": "---\n\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# Prepare servers\n- import_playbook: build.yml\n# Add monitoring\n#- import_playbook: elk.yml\n\n# --------------------------------------------------------------------\n# VM ready - start insert specific scenario\n# --------------------------------------------------------------------\n# Turn server into DC and load active directory data (users/groups/ou)\n#- import_playbook: ad.yml\n# create main domains, child domain and enroll servers\n\n## AD ----------\n- import_playbook: ad-servers.yml\n- import_playbook: ad-parent_domain.yml\n- import_playbook: ad-child_domain.yml\n- import_playbook: ad-members.yml\n# create the trust relationships\n- import_playbook: ad-trusts.yml\n# import the ad datas : users/groups...\n- import_playbook: ad-data.yml\n# set the GMAS accounts\n- import_playbook: ad-gmsa.yml\n# install LAPS\n- import_playbook: laps.yml\n- import_playbook: localusers.yml\n## MSSQL + IIS  ----------\n# configure servers vulns (done in the middle of ad install to let time before install relations and acl)\n#- import_playbook: servers.yml\n## AD - servers localgroup + rdp + inter domain relations & acl\n# set the rights and the group domains relations\n- import_playbook: ad-relations.yml\n# set adcs\n- import_playbook: adcs.yml\n# set the ACL\n- import_playbook: ad-acl.yml\n\n## SERVERS ---------\n### MSSQL + IIS  ----------\n# configure servers vulns (done in the midle of ad install to let time before install relations and acl)\n- import_playbook: servers.yml\n\n## SECURITY -----\n# --------------------------------------------------------------------\n# specifics security linked to the scenario are here\n- import_playbook: security.yml\n# --------------------------------------------------------------------\n# specifics vulns linked to the scenario are here\n- import_playbook: vulnerabilities.yml\n\n- import_playbook: reboot.yml\n"
  },
  {
    "path": "ansible/onlyusers.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# set AD datas ==================================================================================================\n- name: DCs AD data configuration\n  hosts: dc01,dc02\n  roles:\n    - { role: 'onlyusers', tags: 'onlyusers' }\n  vars:\n    hostname: \"{{lab.hosts[dict_key].hostname}}\"\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    domain_server: \"{{lab.hosts[dict_key].hostname}}.{{domain}}\"\n    ad_users: \"{{lab.domains[lab.hosts[dict_key].domain].users}}\"\n    ad_ou: \"{{lab.domains[lab.hosts[dict_key].domain].organisation_units}}\"\n    ad_groups: \"{{lab.domains[lab.hosts[dict_key].domain].groups}}\"\n"
  },
  {
    "path": "ansible/private_data_dir/.git_keep",
    "content": ""
  },
  {
    "path": "ansible/reboot.yml",
    "content": "- name: \"Reboot all\"\n  hosts: domain\n  tasks:\n    - name: \"reboot\"\n      win_reboot:\n        reboot_timeout: 1000\n        post_reboot_delay: 200\n"
  },
  {
    "path": "ansible/requirements.yml",
    "content": "---\ncollections:\n  # Install a collection from Ansible Galaxy.\n  - name: ansible.windows\n    version: 1.11.0\n  - name: community.general\n  - name: community.windows\n    version: 1.11.0\n  - name: chocolatey.chocolatey\n  - name: community.crypto\n  - name: community.mysql\n  - name: scicore.guacamole\n  - name: ansible.posix\n# - name: goad.windows\n#   type: dir\n#   source: ./collections/goad/windows\nroles:\n  - name: geerlingguy.mysql"
  },
  {
    "path": "ansible/requirements_311.yml",
    "content": "---\ncollections:\n  # Install a collection from Ansible Galaxy.\n  # ansible.windows 2.5.0 and community.windows 2.3.0 need ansible-core >= 2.16\n  - name: ansible.windows\n    version: 2.5.0\n  - name: community.general\n  - name: community.windows\n    version: 2.3.0\n  - name: chocolatey.chocolatey\n  - name: community.crypto\n  - name: community.mysql\n  - name: scicore.guacamole\n  - name: ansible.posix\n# - name: goad.windows\n#   type: dir\n#   source: ./collections/goad/windows\nroles:\n  - name: geerlingguy.mysql"
  },
  {
    "path": "ansible/roles/acl/tasks/main.yml",
    "content": "# acl : $for, $to, $right, $inheritance\n## acl values :\n# AccessSystemSecurity\n# CreateChild\n# Delete\n# DeleteChild\n# DeleteTree\n# ExtendedRight\n# GenericAll\n# GenericExecute\n# GenericRead\n# GenericWrite\n# ListChildren\n# ListObject\n# ReadControl\n# ReadProperty\n# Self\n# Synchronize\n# WriteDacl\n# WriteOwner\n# WriteProperty \n\n## extend rights\n# \"00299570-246d-11d0-a768-00aa006e0529\" {$right = \"User-Force-Change-Password\"}\n# \"45ec5156-db7e-47bb-b53f-dbeb2d03c40\"  {$right = \"Reanimate-Tombstones\"}\n# \"bf9679c0-0de6-11d0-a285-00aa003049e2\" {$right = \"Self-Membership\"}\n# \"ba33815a-4f93-4c76-87f3-57574bff8109\" {$right = \"Manage-SID-History\"}\n# \"1131f6ad-9c07-11d1-f79f-00c04fc2dcd2\" {$right = \"DS-Replication-Get-Changes-All\"}\n\n#  Get-ADObject -SearchBase \"CN=Extended-Rights,CN=Configuration,DC=essos,DC=local\" -Filter * -Properties cn, ObjectGUID | Select-Object cn, ObjectGUID\n# Extended-Rights                               9b7d2c93-d499-4596-9ca3-a695b6be465c\n# Domain-Administer-Server                      e504244d-e1fd-488f-b37a-f314c05a7d32\n# User-Change-Password                          0fe73392-46e1-4731-ae36-ad5d6760e94b\n# User-Force-Change-Password                    8f310920-3501-44e1-afdb-516998f3cd5b\n# Send-As                                       97f3ed7d-9c14-430e-aab9-e82690b75031\n# Receive-As                                    5db63385-e52e-4670-8dc6-127efe1f258f\n# Send-To                                       c97bf0b2-1b6d-41bf-b3f3-81ebcf7191f2\n# Domain-Password                               df29d475-85f2-4dab-88e9-08cb71f09f98\n# General-Information                           b49543a3-93f4-4693-9022-dc4e031cd37a\n# User-Account-Restrictions                     57280d2c-63d6-48c3-8940-40a0386e441a\n# User-Logon                                    5de54ab3-cf92-4fcc-a02c-32f3dd8f033b\n# Membership                                    150db84e-e0d2-4ced-ad78-fb308a1e36ae\n# Open-Address-Book                             4ab03696-d857-4eda-9e3b-66f7d4ca7c1d\n# Personal-Information                          7c087e49-548d-4452-99a4-897f719c9714\n# Email-Information                             f44205ea-d22e-45a4-8df6-f1f62af91fa1\n# Web-Information                               ff5ce5c7-d610-43ac-9b4c-1f54c706a4ec\n# DS-Replication-Get-Changes                    89359caf-885d-4bfd-86f7-597da344cd31\n# DS-Replication-Synchronize                    ea24c9cb-16de-40d5-a7b9-c7bd2829eb54\n# DS-Replication-Manage-Topology                6f645ad8-d1ce-4b55-b819-40c567a47d7d\n# Change-Schema-Master                          51be0e75-2826-4a30-852a-6599e575dea5\n# Change-Rid-Master                             8640f02c-ae7e-4929-9b80-9a07e96aa2bc\n# Do-Garbage-Collection                         b566d20b-8b6e-49bd-a030-44fd25e97011\n# Recalculate-Hierarchy                         21a0fc05-d231-4d88-91da-6c1b3fe95592\n# Allocate-Rids                                 fb0c09dd-dd98-4d08-8db7-ed56a4a37f47\n# Change-PDC                                    a2f51b25-6271-450d-97de-0e92ccd021ec\n# Add-GUID                                      b1140d87-5635-4307-b53b-e0149c7c0c05\n# Change-Domain-Master                          ac9a0b36-26a6-42eb-bb86-418cdf69b7f4\n# Public-Information                            05fd7211-4774-4aad-9758-aadc0c06769c\n# msmq-Receive-Dead-Letter                      0c5a23eb-6e08-4e42-8fcb-9848c669a958\n# msmq-Peek-Dead-Letter                         3f61a921-fe0c-4735-94ad-5c2c99772eee\n# msmq-Receive-computer-Journal                 c9466a99-d3fa-4ee9-a3cf-ebb5fd0522cb\n# msmq-Peek-computer-Journal                    1d474c11-cf1a-4507-bf24-6b62aa873e3f\n# msmq-Receive                                  4ebf186e-d85e-4b3f-af0e-1a82f0a91006\n# msmq-Peek                                     cc1d853f-3eb7-416f-8fb8-1133038015ce\n# msmq-Send                                     726e07c2-447b-49f0-a9ab-32b048d93ab5\n# msmq-Receive-journal                          61944b74-1fd1-4eb3-9c26-7f048d3c2ad9\n# msmq-Open-Connector                           09e074fc-580f-4438-aa55-d33ffe43d65c\n# Apply-Group-Policy                            63231ba7-f6a1-4483-8a0d-6e019f050d74\n# RAS-Information                               4772e2b5-8517-431b-a527-550dcd82871b\n# DS-Install-Replica                            b4071e8e-db74-4015-9d22-e962e857be10\n# Change-Infrastructure-Master                  0d20b469-65d4-4ce0-a3c8-b03090c7ac70\n# Update-Schema-Cache                           2f96d806-c550-49ae-8c2a-6e3651687035\n# Recalculate-Security-Inheritance              85473cfe-ebdb-479e-982e-e52dc5b548a6\n# DS-Check-Stale-Phantoms                       2908d21c-de4d-435a-b974-432e09e8ed36\n# Certificate-Enrollment                        1458779e-3d29-481c-82bf-20a4ba791658\n# Self-Membership                               f795df1b-c7dd-496e-a319-26619a97fde9\n# Validated-DNS-Host-Name                       5db425b7-a9f9-482c-b820-2a285504d166\n# Validated-SPN                                 fd8881f1-eeb8-4836-b34f-df39cb97bc03\n# Generate-RSoP-Planning                        6f03801a-778b-4062-bc65-2ddf73e4e86d\n# Refresh-Group-Cache                           d30727a5-60d9-4919-aa47-6e428029373f\n# SAM-Enumerate-Entire-Domain                   ff9e23a3-a840-4bf1-8a54-d29c33e52074\n# Generate-RSoP-Logging                         8668e4d2-e4d7-4c31-8bab-df1e323542de\n# Domain-Other-Parameters                       8accf218-351b-4bfc-b052-4bc0483cafc0\n# DNS-Host-Name-Attributes                      9f6cd937-1747-4c31-bcc1-3b0bb215c2ad\n# Create-Inbound-Forest-Trust                   b8c8ae65-b61b-490b-9b18-85ef0671df3a\n# DS-Replication-Get-Changes-All                0ea8ddf5-200e-4fd7-b8a7-bf700fe1c9db\n# Migrate-SID-History                           bb7a33cc-718a-4e99-813f-7bc7045b5f0d\n# Reanimate-Tombstones                          a65ee3f0-0e3e-46c3-81b1-69a00561e7e9\n# Allowed-To-Authenticate                       378c1b73-0d0c-4233-8da4-f4535bdadcd4\n# DS-Execute-Intentions-Script                  31f3b31b-499e-42a8-98bc-55b80501a588\n# DS-Replication-Monitor-Topology               878775ad-2ca5-4f18-a198-8256f9f8ef0c\n# Update-Password-Not-Required-Bit              567c4967-5ea7-401f-b365-e978f43edf1a\n# Unexpire-Password                             72fb83c4-6bc8-41bb-8488-dfbf29ce68f0\n# Enable-Per-User-Reversibly-Encrypted-Password d7fb9493-ffb9-4fee-843b-f486a544fa32\n# DS-Query-Self-Quota                           2a7e864d-f9f4-452f-b148-f0f1fe48cc6c\n# Private-Information                           3eb80fd9-0fe3-4063-89c6-32c43c6f602f\n# Read-Only-Replication-Secret-Synchronization  68d62c55-f3bd-44e4-bbba-ec5173dfbc86\n# MS-TS-GatewayAccess                           4ed4306b-b193-40fa-b6ac-51acbd82569d\n# Terminal-Server-License-Server                d3b3de9b-05c3-412c-9ce4-4d4a073161be\n# Reload-SSL-Certificate                        fa6d2bac-0dab-4d70-8648-66b93c13171c\n# DS-Replication-Get-Changes-In-Filtered-Set    3a4a7690-91a4-40c8-aa89-523c49ab59d3\n# Run-Protect-Admin-Groups-Task                 dee4aa72-8eff-488a-8182-409f5a6f9e67\n# Manage-Optional-Features                      52ccd3e5-4d18-4e65-9d94-f3174adda90f\n# DS-Clone-Domain-Controller                    836bcd2f-26e9-4146-87bc-c107c7756738\n# Validated-MS-DS-Behavior-Version              139b1950-1b1a-4860-a69f-926625092d5a\n# Validated-MS-DS-Additional-DNS-Host-Name      f6f2c8f1-5779-4f89-8799-e180542e6e40\n# Certificate-AutoEnrollment                    162d653a-4488-4ec5-ad04-a46f65592d4d\n# DS-Set-Owner                                  99044f51-e9f8-4ca4-a691-7d1f632419c3\n# DS-Bypass-Quota                               d20edcfd-2ab2-4f2f-be8b-935dd601441c\n# DS-Read-Partition-Secrets                     01e1f66d-11b4-4d9a-9345-33f28a7b9b58\n# DS-Write-Partition-Secrets                    fe22431d-3aba-449c-9ff9-2d41fc97132e\n# DS-Validated-Write-Computer                   cbcc2342-ae9b-442a-8a18-a076ecc849ca\n\n# acl extended values allowed : \n# Ext-User-Force-Change-Password', 'Ext-Self-Self-Membership', 'Ext-Write-Self-Membership'\n# ACL abuse scenarios\n# https://sensepost.com/blog/2020/ace-to-rce/\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces\n# https://adsecurity.org/?p=3658\n# https://docs.microsoft.com/en-us/previous-versions/tn-archive/ff405676(v=msdn.10)\n\n- name: set acl \n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $for,\n\n          [String]\n          $to,\n\n          [String]\n          $right,\n\n          [String]\n          $inheritance\n      )\n      Import-Module ActiveDirectory\n      Set-Location AD:\n      $aclValues = 'AccessSystemSecurity', 'CreateChild', 'Delete', 'DeleteChild', 'DeleteTree', 'ExtendedRight', 'GenericAll', 'GenericExecute', 'GenericRead', 'GenericWrite', 'ListChildren', 'ListObject', 'ReadControl', 'ReadProperty', 'Self', 'Synchronize', 'WriteDacl', 'WriteOwner', 'WriteProperty'\n      $aclExtendValues = 'Ext-User-Force-Change-Password',\n                   'Ext-Self-Self-Membership',\n                   'Ext-Write-Self-Membership',\n                   'Ext-ManageCA',\n                   'Ext-Write-SPN'\n      if ($for.StartsWith(\"NT AUTHORITY\")) {\n        $forSID = New-Object System.Security.Principal.NTAccount \"$for\"\n      } else {\n        $forSID = New-Object System.Security.Principal.SecurityIdentifier (Get-ADObject -Filter \"SamAccountName -eq '$for'\" -Properties objectSID).objectSID\n      }\n\n      try {\n        $objAcl = get-acl -Path \"$to\" -ErrorAction Stop\n        $objOU = $to\n        $objFound=$true\n      } catch [System.Management.Automation.ItemNotFoundException]{\n        $objFound=$false\n      }\n\n      if (-not $objFound) {\n        $extra_args = @{}\n        if ($to -match \"\\\\\") {\n          $extra_args.Server = $to.Split(\"\\\")[0]\n          $to = $to.Split(\"\\\")[1]\n        }\n        $toObj = Get-ADObject -Filter \"SamAccountName -eq '$to'\" @extra_args\n        $objOU = ($toObj).DistinguishedName\n        $objAcl = get-acl -Path \"$objOU\"\n      }\n\n      $type =  [System.Security.AccessControl.AccessControlType] \"Allow\"\n      $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] $inheritance\n\n      $aclExtendedValueRightGUID = @{\n        \"Ext-User-Force-Change-Password\" = @(\"ExtendedRight\",\"00299570-246d-11d0-a768-00aa006e0529\")\n        \"Ext-Write-Self-Membership\" = @(\"WriteProperty\",\"bf9679c0-0de6-11d0-a285-00aa003049e2\")\n        \"Ext-Self-Self-Membership\" = @(\"Self\",\"bf9679c0-0de6-11d0-a285-00aa003049e2\")\n        \"Ext-ManageCA\" = @(\"ExtendedRight\",\"18e470eb-9b98-47c5-896e-146c5c77100d\")\n        \"Ext-Write-SPN\" = @(\"WriteProperty\",\"f3a64788-5306-11d1-a9c5-0000f80367c1\")\n      }\n\n      $Ansible.Changed = $false\n      if ($aclValues.contains($right)) {\n        $adRight =  [System.DirectoryServices.ActiveDirectoryRights] $right\n        $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $forSID,$adRight,$type,$inheritanceType\n      }\n      if ($aclExtendValues.contains($right)) {\n        $extendedRightGUID = $aclExtendedValueRightGUID[$right][1]\n        $extright = $aclExtendedValueRightGUID[$right][0]\n        $adRight =  [System.DirectoryServices.ActiveDirectoryRights] $extright\n        $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $forSID,$extright,$type,$extendedRightGUID,$inheritanceType\n      }\n      if ($ace) {\n        $objAcl.AddAccessRule($ace)\n        Set-Acl -AclObject $objAcl -path \"$objOU\"\n        $Ansible.Changed = $true\n      }\n    parameters:\n      for: \"{{item.value.for}}\"\n      to: \"{{item.value.to}}\"\n      right: \"{{item.value.right}}\"\n      inheritance: \"{{item.value.inheritance}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  with_dict: \"{{ ad_acls }}\""
  },
  {
    "path": "ansible/roles/ad/tasks/groups.yml",
    "content": "# https://clintboessen.blogspot.com/2010/04/group-scopes.html\n# https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc755692(v=ws.10)\n- name: Create Groups Universal\n  win_domain_group:\n    name: \"{{ item.key }}\"\n    scope: universal\n    path: \"{{item.value.path}}\"\n    state: present\n  with_dict: \"{{ ad_groups['universal'] }}\"\n  when: ad_groups['universal'] is defined\n\n- name: Create Groups Global\n  win_domain_group:\n    name: \"{{ item.key }}\"\n    scope: global\n    path: \"{{item.value.path}}\"\n    state: present\n  with_dict: \"{{ ad_groups['global'] }}\"\n  when: ad_groups['global'] is defined\n\n- name: Create Groups domainlocal\n  win_domain_group:\n    name: \"{{ item.key }}\"\n    scope: domainlocal\n    path: \"{{item.value.path}}\"\n    state: present\n  with_dict: \"{{ ad_groups['domainlocal'] }}\"\n  when: ad_groups['domainlocal'] is defined"
  },
  {
    "path": "ansible/roles/ad/tasks/main.yml",
    "content": "- name: Ensure Administrator is part of Domain Admins\n  win_domain_group_membership:\n    name: \"Domain Admins\"\n    members:\n      - Administrator\n    state: present\n\n- name: organisation units\n  import_tasks: ou.yml\n\n- name: groups\n  import_tasks: groups.yml\n\n- name: users\n  import_tasks: users.yml\n\n# Managed BY\n- name: Assign managed_by domainlocal groups\n  win_domain_group:\n    name: \"{{ item.key }}\"\n    managed_by: \"{{ item.value.managed_by }}\"\n  with_dict: \"{{ ad_groups['domainlocal'] }}\"\n  when: ad_groups['domainlocal'] is defined and item.value.managed_by is defined\n\n- name: Assign managed_by universal groups\n  win_domain_group:\n    name: \"{{ item.key }}\"\n    managed_by: \"{{ item.value.managed_by }}\"\n  with_dict: \"{{ ad_groups['universal'] }}\"\n  when: ad_groups['universal'] is defined and item.value.managed_by is defined\n\n- name: Assign managed_by global groups\n  win_domain_group:\n    name: \"{{ item.key }}\"\n    managed_by: \"{{ item.value.managed_by }}\"\n  with_dict: \"{{ ad_groups['global'] }}\"\n  when: ad_groups['global'] is defined and item.value.managed_by is defined\n\n# Add members\n- name: Add members to the Universal group, preserving existing membership\n  community.windows.win_domain_group_membership:\n    name: \"{{ item.key }}\"\n    members: \"{{ item.value.members }}\"\n  with_dict: \"{{ ad_groups['universal'] }}\"\n  when: ad_groups['universal'] is defined and item.value.members is defined\n\n- name: Add members to the Global group, preserving existing membership\n  community.windows.win_domain_group_membership:\n    name: \"{{ item.key }}\"\n    members: \"{{ item.value.members }}\"\n  with_dict: \"{{ ad_groups['global'] }}\"\n  when: ad_groups['global'] is defined and item.value.members is defined\n\n- name: Add members to the Domainlocal group, preserving existing membership\n  community.windows.win_domain_group_membership:\n    name: \"{{ item.key }}\"\n    members: \"{{ item.value.members }}\"\n  with_dict: \"{{ ad_groups['domainlocal'] }}\"\n  when: ad_groups['domainlocal'] is defined and item.value.members is defined"
  },
  {
    "path": "ansible/roles/ad/tasks/ou.yml",
    "content": "- name: \"Create OU\"\n  win_dsc:\n    resource_name: ADOrganizationalUnit\n    name: \"{{ item.key }}\"\n    path:  \"{{ item.value.path }}\"\n  with_dict: \"{{ad_ou}}\""
  },
  {
    "path": "ansible/roles/ad/tasks/users.yml",
    "content": "- name: Sync the contents of one directory to another - hack to get Requires -Module Ansible.ModuleUtils.Legacy loaded\n  community.windows.win_robocopy:\n    src: C:\\windows\\temp\n    dest: C:\\windows\\temp\n\n- name: \"Create users\"\n  win_domain_user:\n    name: \"{{ item.key }}\"\n    firstname: \"{{item.value.firstname}}\"\n    surname: \"{{ item.value.surname | default(item.value.firstname) }}\"\n    password: \"{{ item.value.password }}\"\n    password_never_expires: yes\n    state: present\n    path: \"{{item.value.path}}\"\n    description: \"{{item.value.description | default('-')}}\"\n    groups: \"{{ item.value.groups}}\"\n    city: \"{{item.value.city | default('-')}}\"\n    domain_username: \"{{domain_username}}\"\n    domain_password: \"{{domain_password}}\"\n  with_dict: \"{{ ad_users }}\"\n  register: usercreate\n  until: \"usercreate is not failed\"\n  retries: 3\n  delay: 30\n\n- name: \"Set users SPN lists\"\n  win_domain_user:\n    name: \"{{ item.key }}\"\n    spn: \"{{item.value.spns}}\"\n    domain_username: \"{{domain_username}}\"\n    domain_password: \"{{domain_password}}\"\n  with_dict: \"{{ ad_users }}\"\n  when: item.value.spns is defined"
  },
  {
    "path": "ansible/roles/adcs/tasks/main.yml",
    "content": "- name: Install ADCS\n  win_feature:\n    name: AD-Certificate\n    state: present\n    include_sub_features: yes\n    include_management_tools: yes\n  register: win_feature\n\n- name: Install-WindowsFeature ADCS-Cert-Authority\n  ansible.windows.win_feature:\n    name: ADCS-Cert-Authority\n    state: present\n    include_management_tools: yes\n\n- name: Install-WindowsFeature ADCS-Web-Enrollment\n  ansible.windows.win_feature:\n    name: ADCS-Web-Enrollment\n    state: present\n  when: ca_web_enrollment\n\n- name: Install-ADCSCertificationAuthority-PS\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $domain_username,\n\n          [String]\n          $domain_password,\n\n          [String]\n          $ca_common_name\n      )\n      $pass = ConvertTo-SecureString $domain_password -AsPlainText -Force\n      $Cred = New-Object System.Management.Automation.PSCredential ($domain_username, $pass)\n      try {\n        Install-AdcsCertificationAuthority -Credential $Cred -CAType EnterpriseRootCA -CryptoProviderName \"RSA#Microsoft Software Key Storage Provider\" -KeyLength 2048 -HashAlgorithmName SHA256 -ValidityPeriod Years -ValidityPeriodUnits 5 -CACommonName $ca_common_name -Force\n        $Ansible.Changed = $true\n      } catch {\n        $Ansible.Changed = $false\n      }\n    error_action: stop\n    parameters:\n      domain_username: \"{{domain_username}}\"\n      domain_password: \"{{domain_password}}\"\n      ca_common_name: \"{{ca_common_name}}\"\n\n# ESC 8\n# ignore error if already installed\n- name: Enable Web enrollement\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param ()\n      try {\n        Install-AdcsWebEnrollment -Force\n        $Ansible.Changed = $true\n      } catch {\n        $Ansible.Changed = $false\n      }\n  when: ca_web_enrollment\n\n- name: Refresh\n  ansible.windows.win_command: gpupdate /force\n\n# - name: Reboot after ADCS installation\n#   win_reboot:\n#   when: win_feature.reboot_required\n"
  },
  {
    "path": "ansible/roles/adcs_templates/files/ADCSTemplate/.gitignore",
    "content": ".DS_Store\n"
  },
  {
    "path": "ansible/roles/adcs_templates/files/ADCSTemplate/ADCSTemplate.psm1",
    "content": "#requires -Version 5.0 -Modules ActiveDirectory\r\n\r\nFunction Get-RandomHex {\r\nparam ([int]$Length)\r\n    $Hex = '0123456789ABCDEF'\r\n    [string]$Return = $null\r\n    For ($i=1;$i -le $length;$i++) {\r\n        $Return += $Hex.Substring((Get-Random -Minimum 0 -Maximum 16),1)\r\n    }\r\n    Return $Return\r\n}\r\n\r\nFunction IsUniqueOID {\r\nparam ($cn,$TemplateOID,$Server,$ConfigNC)\r\n    $Search = Get-ADObject -Server $Server `\r\n        -SearchBase \"CN=OID,CN=Public Key Services,CN=Services,$ConfigNC\" `\r\n        -Filter {cn -eq $cn -and msPKI-Cert-Template-OID -eq $TemplateOID}\r\n    If ($Search) {$False} Else {$True}\r\n}\r\n\r\nFunction New-TemplateOID {\r\nParam($Server,$ConfigNC)\r\n    <#\r\n    OID CN/Name                                                         [10000000-99999999].[32 hex characters (MD5hash)]\r\n    OID msPKI-Cert-Template-OID    [Forest base OID].[1000000-99999999].[10000000-99999999]  <--- second number same as first number in OID name\r\n    #>\r\n    do {\r\n        $OID_Part_1 = Get-Random -Minimum 10000000 -Maximum 99999999\r\n        $OID_Part_2 = Get-Random -Minimum 10000000 -Maximum 99999999\r\n        $OID_Part_3 = Get-RandomHex -Length 32\r\n        $OID_Forest = Get-ADObject -Server $Server `\r\n            -Identity \"CN=OID,CN=Public Key Services,CN=Services,$ConfigNC\" `\r\n            -Properties msPKI-Cert-Template-OID |\r\n            Select-Object -ExpandProperty msPKI-Cert-Template-OID\r\n        $msPKICertTemplateOID = \"$OID_Forest.$OID_Part_1.$OID_Part_2\"\r\n        $Name = \"$OID_Part_2.$OID_Part_3\"\r\n    } until (IsUniqueOID -cn $Name -TemplateOID $msPKICertTemplateOID -Server $Server -ConfigNC $ConfigNC)\r\n    Return @{\r\n        TemplateOID  = $msPKICertTemplateOID\r\n        TemplateName = $Name\r\n    }\r\n}\r\n\r\n\r\n<#\r\n.SYNOPSIS\r\nReturns the properties of either a single or all Active Directory Certificate Template(s).\r\n.DESCRIPTION\r\nReturns the properties of either a single or list of Active Directory Certificate Template(s)\r\ndepending on whether a DisplayName parameter was passed.\r\n.PARAMETER DisplayName\r\nName of an AD CS template to retrieve.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.EXAMPLE\r\nPS C:\\> Get-ADCSTemplate\r\n.EXAMPLE\r\nPS C:\\> Get-ADCSTemplate -DisplayName PowerShellCMS\r\n.EXAMPLE\r\nPS C:\\> Get-ADCSTemplate | Sort-Object Name | ft Name, Created, Modified\r\n.EXAMPLE\r\nPS C:\\> ###View template permissions\r\n(Get-ADCSTemplate pscms).nTSecurityDescriptor\r\n(Get-ADCSTemplate pscms).nTSecurityDescriptor.Sddl\r\n(Get-ADCSTemplate pscms).nTSecurityDescriptor.Access\r\nConvertFrom-SddlString -Sddl (Get-ADCSTemplate pscms).nTSecurityDescriptor.sddl -Type ActiveDirectoryRights\r\n.NOTES\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n#>\r\nFunction Get-ADCSTemplate {\r\nparam(\r\n    [parameter(Position=0)]\r\n    [string]\r\n    $DisplayName,\r\n\r\n    [string]\r\n    $Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\r\n)\r\n    If ($PSBoundParameters.ContainsKey('DisplayName')) {\r\n        $LDAPFilter = \"(&(objectClass=pKICertificateTemplate)(displayName=$DisplayName))\"\r\n    } Else {\r\n        $LDAPFilter = '(objectClass=pKICertificateTemplate)'\r\n    }\r\n\r\n    $ConfigNC     = $((Get-ADRootDSE -Server $Server).configurationNamingContext)\r\n    $TemplatePath = \"CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n    Get-ADObject -SearchScope Subtree -SearchBase $TemplatePath -LDAPFilter $LDAPFilter -Properties * -Server $Server\r\n}\r\n\r\n\r\n<#\r\n.SYNOPSIS\r\nAdds an ACL to an Active Directory Certificate template.\r\n.DESCRIPTION\r\nAdds an ACL to an Active Directory Certificate template.\r\nDefault permission is read (without the Enroll or AutoEnroll switches).\r\n.PARAMETER DisplayName\r\nName of an AD CS template to receive the ACL.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.PARAMETER Type\r\nACL type: Allow or Deny\r\n.PARAMETER Identity\r\nString or string array of Active Directory identities (users or groups)\r\n.PARAMETER Enroll\r\nSet the Enroll permission\r\n.PARAMETER AutoEnroll\r\nSet the AutoEnroll permission\r\n.EXAMPLE\r\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Allow -Identity 'CONTOSO\\Servers Group' -Enroll\r\n.EXAMPLE\r\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Allow -Identity 'CONTOSO\\Servers Group','CONTOSO\\Workstations Group' -Enroll -AutoEnroll\r\n.EXAMPLE\r\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Deny -Identity 'CONTOSO\\Servers Group'\r\n.NOTES\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n#>\r\nFunction Set-ADCSTemplateACL {\r\nparam(\r\n    [parameter(Mandatory)]\r\n    [string]$DisplayName,\r\n    [string]$Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0],\r\n    [ValidateSet('Allow','Deny')]\r\n    [string]$Type = 'Allow',\r\n    [string[]]$Identity,\r\n    [switch]$Enroll,\r\n    [switch]$AutoEnroll\r\n)\r\n    ## Potential issue here that the AD: drive may not be targetting the selected DC in the -SERVER parameter\r\n    $TemplatePath        = \"AD:\\\" + (Get-ADCSTemplate -DisplayName $DisplayName -Server $Server).DistinguishedName\r\n    $acl                 = Get-ACL $TemplatePath\r\n    $InheritedObjectType = [GUID]'00000000-0000-0000-0000-000000000000'\r\n    ForEach ($Group in $Identity) {\r\n        $account = New-Object System.Security.Principal.NTAccount($Group)\r\n        $sid     = $account.Translate([System.Security.Principal.SecurityIdentifier])\r\n\r\n        If ($Type -ne 'Deny') {\r\n            # Read, but only if Allow\r\n            $ObjectType = [GUID]'00000000-0000-0000-0000-000000000000'\r\n            $ace        = New-Object System.DirectoryServices.ActiveDirectoryAccessRule `\r\n                $sid, 'GenericRead', $Type, $ObjectType, 'None', $InheritedObjectType\r\n            $acl.AddAccessRule($ace)\r\n        }\r\n\r\n        If ($Enroll) {\r\n            $ObjectType = [GUID]'0e10c968-78fb-11d2-90d4-00c04f79dc55'\r\n            $ace        = New-Object System.DirectoryServices.ActiveDirectoryAccessRule `\r\n                $sid, 'ExtendedRight', $Type, $ObjectType, 'None', $InheritedObjectType\r\n            $acl.AddAccessRule($ace)\r\n        }\r\n\r\n        If ($AutoEnroll) {\r\n            $ObjectType = [GUID]'a05b8cc2-17bc-4802-a710-e7c15ab866a2'\r\n            $ace        = New-Object System.DirectoryServices.ActiveDirectoryAccessRule `\r\n                $sid, 'ExtendedRight', $Type, $ObjectType, 'None', $InheritedObjectType\r\n            $acl.AddAccessRule($ace)\r\n        }\r\n    }\r\n    Set-ACL $TemplatePath -AclObject $acl\r\n}\r\n\r\n\r\n<#\r\n.SYNOPSIS\r\nReturns a JSON string with the properties of an Active Directory certificate template.\r\n.DESCRIPTION\r\nReturns a JSON string with the properties of an Active Directory certificate template.\r\nBy default returns only the PKI-related properties of the object. These properties are\r\nsufficient for passing to the New-ADCSTemplate function.\r\n.PARAMETER DisplayName\r\nDisplayName for the certificate to export.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.PARAMETER Detailed\r\nIncludes all ADObject properties of the template. These are not required for \r\nuse with the New-ADCSTemplate function.\r\n.NOTES\r\nC.R.U.D. AD CS Template Operations in this module.\r\nNo longer have to use the cert GUI to clone a template and build a new one.\r\nCreate one manually the first time in the GUI, then export it to JSON.\r\nPass the JSON in your new environment (file, here string, DSC, etc.) to build from scratch.\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n.EXAMPLE\r\nPS C:\\> Export-ADCSTemplate -DisplayName PowerShellCMS\r\n.EXAMPLE\r\nPS C:\\> Export-ADCSTemplate -DisplayName PowerShellCMS -Detailed\r\n.EXAMPLE\r\n### Backup all the templates to JSON\r\nmd C:\\ADCSTemplates -ErrorAction SilentlyContinue\r\ncd C:\\ADCSTemplates\r\n(Get-ADCSTemplate).name | ForEach-Object {\"Exporting $_\"; Export-ADCSTemplate -DisplayName $_ | Out-File .\\$_.json -Force}\r\ndir\r\n.EXAMPLE\r\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS-NEW -JSON (Export-ADCSTemplate -DisplayName PowerShellCMS-OLD)\r\n#>\r\nFunction Export-ADCSTemplate {\r\nparam(\r\n    [parameter(Mandatory)]\r\n    [string]$DisplayName,\r\n    [string]$Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0],\r\n    [switch]$Detailed   # Detailed output is not required for export/import. Use for documentation/backup purposes.\r\n)\r\n    If ($Detailed) {\r\n        Get-ADCSTemplate -DisplayName $DisplayName -Server $Server |\r\n            ConvertTo-Json\r\n    } Else {\r\n        Get-ADCSTemplate -DisplayName $DisplayName -Server $Server |\r\n            Select-Object -Property name, displayName, objectClass, flags, revision, *pki* |\r\n            ConvertTo-Json\r\n    }\r\n}\r\n\r\n<#\r\n.SYNOPSIS\r\nCreates a new Active Directory Certificate Services template based on a JSON export.\r\n.DESCRIPTION\r\nCreates a new Active Directory Certificate Services template based on a JSON export.\r\nOptionally can permission and publish the template (best practice).\r\n.PARAMETER DisplayName\r\nDisplayName for the certificate template to create. This does not have to match\r\nthe original name of the exported template.\r\n.PARAMETER JSON\r\nJSON string output from Export-ADCSTemplate. Defines the template to create.\r\nCan be retrieved from file using Get-Content -Raw.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.PARAMETER Identity\r\nString or string array of Active Directory identities (users or groups).\r\nThis is optional for permissioning the template.\r\n.PARAMETER AutoEnroll\r\nDefault permission is Read and Enroll. Use this switch to also grant AutoEnroll \r\nto the identity. Only used when Identity parameter is used.\r\n.PARAMETER Publish\r\nPublish the template to *ALL* Certificate Authority issuers. Use with caution\r\nin production environments. You may want to manually publish to only specific\r\nCertificate Authorities in production. In a lab this is ideal.\r\n.NOTES\r\nThis function does not use the official (complicated) API for PKI management.\r\nInstead it creates the exact same AD objects that are generated by the API,\r\nincluding AD forest-specific OIDs.\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n.EXAMPLE\r\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS -JSON (Get-Content .\\pscms.json -Raw)\r\n.EXAMPLE\r\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS -JSON (Get-Content .\\pscms.json -Raw) -Server dc1.contoso.com -Identity G_DSCNodes -AutoEnroll -Publish\r\n\r\n# From a client configured for AD CS autoenrollment:\r\n$Req = @{\r\n    Template          = 'PowerShellCMS'\r\n    Url               = 'ldap:'\r\n    CertStoreLocation = 'Cert:\\LocalMachine\\My'\r\n}\r\nGet-Certificate @Req\r\n# Note: If you have the Carbon module installed, it conflicts with Get-Certificate native cmdlet.\r\n\r\n$DocEncrCert = (dir Cert:\\LocalMachine\\My -DocumentEncryptionCert | Sort-Object NotBefore)[-1]\r\nProtect-CmsMessage -To $DocEncrCert -Content \"Encrypted with my new cert from the new template!\"\r\n.EXAMPLE\r\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS-NEW -JSON (Export-ADCSTemplate -DisplayName PowerShellCMS-OLD)\r\n#>\r\nFunction New-ADCSTemplate {\r\nparam(\r\n    [parameter(Mandatory)]\r\n    [string]$DisplayName,   # name in JSON export is ignored\r\n    [parameter(Mandatory)]\r\n    [string]$JSON,\r\n    [string]$Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0],\r\n    [string[]]$Identity, # = \"$((Get-ADDomain).NetBIOSName)\\Domain Computers\",\r\n    [switch]$AutoEnroll,\r\n    [switch]$Publish\r\n)\r\n    ### Put GroupName and AutoEnroll into a parameter set\r\n\r\n    # Manually import AD module to get AD: drive used later for permissions\r\n    Import-Module ActiveDirectory -Verbose:$false\r\n\r\n    $ConfigNC = $((Get-ADRootDSE -Server $Server).configurationNamingContext)\r\n\r\n    #region CREATE OID\r\n    <#\r\n    CN                              : 14891906.F2AC4390685318BD1D950A66EDB50FF4\r\n    DisplayName                     : TemplateNameHere\r\n    DistinguishedName               : CN=14891906.F2AC4390685318BD1D950A66EDB50FF4,CN=OID,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=com\r\n    dSCorePropagationData           : {1/1/1601 12:00:00 AM}\r\n    flags                           : 1\r\n    instanceType                    : 4\r\n    msPKI-Cert-Template-OID         : 1.3.6.1.4.1.311.21.8.11489019.14294623.5588661.594850.12204198.151.6616009.14891906\r\n    Name                            : 14891906.F2AC4390685318BD1D950A66EDB50FF4\r\n    ObjectCategory                  : CN=ms-PKI-Enterprise-Oid,CN=Schema,CN=Configuration,DC=contoso,DC=com\r\n    ObjectClass                     : msPKI-Enterprise-Oid\r\n    #>\r\n    $OID = New-TemplateOID -Server $Server -ConfigNC $ConfigNC\r\n    $TemplateOIDPath = \"CN=OID,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n    $oa = @{\r\n\t    'DisplayName' = $DisplayName\r\n\t    'flags' = [System.Int32]'1'\r\n\t    'msPKI-Cert-Template-OID' = $OID.TemplateOID\r\n    }\r\n    New-ADObject -Path $TemplateOIDPath -OtherAttributes $oa -Name $OID.TemplateName -Type 'msPKI-Enterprise-Oid' -Server $Server\r\n    #endregion\r\n\r\n    #region CREATE TEMPLATE\r\n    # https://docs.microsoft.com/en-us/powershell/dsc/securemof#certificate-requirements\r\n    # https://blogs.technet.microsoft.com/option_explicit/2012/04/09/pki-certificates-and-the-x-509-standard/\r\n    # https://technet.microsoft.com/en-us/library/cc776447(v=ws.10).aspx\r\n    $import = $JSON | ConvertFrom-Json\r\n    $oa = @{ 'msPKI-Cert-Template-OID' = $OID.TemplateOID }\r\n    ForEach ($prop in ($import | Get-Member -MemberType NoteProperty)) {\r\n        Switch ($prop.Name) {\r\n            { $_ -in 'flags',\r\n                    'msPKI-Certificate-Name-Flag',\r\n                    'msPKI-Enrollment-Flag',\r\n                    'msPKI-Minimal-Key-Size',\r\n                    'msPKI-Private-Key-Flag',\r\n                    'msPKI-Template-Minor-Revision',\r\n                    'msPKI-Template-Schema-Version',\r\n                    'msPKI-RA-Signature',\r\n                    'pKIMaxIssuingDepth',\r\n                    'pKIDefaultKeySpec',\r\n                    'revision'\r\n            } { $oa.Add($_,[System.Int32]$import.$_); break }\r\n\r\n            { $_ -in 'msPKI-Certificate-Application-Policy',\r\n                    'pKICriticalExtensions',\r\n                    'pKIDefaultCSPs',\r\n                    'pKIExtendedKeyUsage',\r\n                    'msPKI-RA-Application-Policies'\r\n            } { $oa.Add($_,[Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]$import.$_); break }\r\n\r\n            { $_ -in 'pKIExpirationPeriod',\r\n                    'pKIKeyUsage',\r\n                    'pKIOverlapPeriod'\r\n            } { $oa.Add($_,[System.Byte[]]$import.$_); break }\r\n\r\n        }\r\n    }\r\n    $TemplatePath = \"CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n    New-ADObject -Path $TemplatePath -OtherAttributes $oa -Name $DisplayName.Replace(' ','') `\r\n        -DisplayName $DisplayName -Type pKICertificateTemplate -Server $Server\r\n    #endregion\r\n\r\n    #region PERMISSIONS\r\n    ## Potential issue here that the AD: drive may not be targetting the selected DC in the -SERVER parameter\r\n    If ($PSBoundParameters.ContainsKey('Identity')) {\r\n        If ($AutoEnroll) {\r\n            Set-ADCSTemplateACL -DisplayName $DisplayName -Server $Server -Type Allow -Identity $Identity -Enroll -AutoEnroll\r\n        } Else {\r\n            Set-ADCSTemplateACL -DisplayName $DisplayName -Server $Server -Type Allow -Identity $Identity -Enroll\r\n        }\r\n    }\r\n    #endregion\r\n\r\n    #region ISSUE\r\n    If ($Publish) {\r\n        ### WARNING: Issues on all available CAs. Test in your environment.\r\n        $EnrollmentPath = \"CN=Enrollment Services,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n        $CAs = Get-ADObject -SearchBase $EnrollmentPath -SearchScope OneLevel -Filter * -Server $Server\r\n        ForEach ($CA in $CAs) {\r\n            Set-ADObject -Identity $CA.DistinguishedName -Add @{certificateTemplates=$DisplayName.Replace(' ','')} -Server $Server\r\n        }\r\n    }\r\n    #endregion\r\n}\r\n\r\n\r\n<#\r\n.SYNOPSIS\r\nRemoves a certificate template from Active Directory.\r\n.DESCRIPTION\r\nRemoves the template from any issuers where it is published.\r\nRemoves the template itself.\r\nRemoves the unique OID object of the template.\r\n.PARAMETER DisplayName\r\nDisplayName for the certificate template to delete.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.EXAMPLE\r\nPS C:\\> Remove-ADCSTemplate -DisplayName PowerShellCMS\r\n.EXAMPLE\r\nPS C:\\> (Get-ADCSTemplate).name | Where-Object {$_ -like \"PowerShellCMS*\"} | ForEach-Object {Remove-ADCSTemplate -DisplayName $_ -Verbose}\r\n.NOTES\r\nUse with caution!\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n#>\r\nFunction Remove-ADCSTemplate {\r\n[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='High')]\r\nparam(\r\n    [parameter(Mandatory)]\r\n    [string]$DisplayName,\r\n    [string]$Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\r\n)\r\n    if ($pscmdlet.ShouldProcess($DisplayName, 'Remove certificate template')) {\r\n        $ConfigNC = $((Get-ADRootDSE -Server $Server).configurationNamingContext)\r\n\r\n        $Template = Get-ADCSTemplate -DisplayName $DisplayName -Server $Server\r\n\r\n        #region REMOVE ISSUE IF IT EXISTS\r\n        $EnrollmentPath = \"CN=Enrollment Services,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n        $CAs = Get-ADObject -SearchBase $EnrollmentPath -SearchScope OneLevel -Filter * -Server $Server\r\n        ForEach ($CA in $CAs) {\r\n            Set-ADObject -Identity $CA.DistinguishedName -Remove @{certificateTemplates=$Template.cn} -Server $Server -Confirm:$false\r\n        }\r\n        #endregion\r\n\r\n        #region REMOVE TEMPLATE\r\n        Remove-ADObject -Identity $Template.distinguishedName -Server $Server -Confirm:$false\r\n        #endregion\r\n\r\n        #region REMOVE OID\r\n        $TemplateOIDPath = \"CN=OID,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n        Get-ADObject -SearchBase $TemplateOIDPath -LDAPFilter \"(DisplayName=$DisplayName)\" -Server $Server | Remove-ADObject -Confirm:$false\r\n        #endregion\r\n    }\r\n}\r\n\r\n\r\n<#\r\n.SYNOPSIS\r\nMaps a PowerShell drive to the Active Directory Certificate Services location.\r\n.DESCRIPTION\r\nMaps a PowerShell drive to the Active Directory Certificate Services location \r\nof the Configuration partition under CN=Public Key Services,CN=Services,... .\r\nThe new drive is ADCS:. This is purely for convenience of checking the objects\r\nupdated by functions in the ADCSTemplate module.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.EXAMPLE\r\nPS C:\\> New-ADCSDrive\r\nPS C:\\> Set-Location ADCS:\r\n.EXAMPLE\r\n### Explore templates with drive\r\nNew-ADCSDrive\r\nGet-PSDrive\r\ncd ADCS:\r\ndir\r\n\r\n# List templates\r\ncd '.\\CN=Certificate Templates'\r\ndir\r\ndir | fl *\r\ndir *WebServer*\r\n\r\n# list CAs\r\ncd \\\r\ncd '.\\CN=Enrollment Services'\r\ndir\r\ncd C:\r\n.NOTES\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n#>\r\nFunction New-ADCSDrive {\r\nparam(\r\n    [string]$Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\r\n)\r\n    $ConfigNC     = $((Get-ADRootDSE -Server $Server).configurationNamingContext)\r\n    New-PSDrive -Name ADCS -PSProvider ActiveDirectory -Root \"CN=Public Key Services,CN=Services,$ConfigNC\" -Server $Server -Scope Global\r\n}\r\n\r\n\r\nExport-ModuleMember -Function *-ADCS*\r\n"
  },
  {
    "path": "ansible/roles/adcs_templates/files/ADCSTemplate/Examples/Build-ADCS.ps1",
    "content": "\n\nconfiguration CreateADDomainWithCS\n{ \n   param \n   ( \n        [Parameter(Mandatory)]\n        [String]$DomainName,\n\n        [Parameter(Mandatory)]\n        [System.Management.Automation.PSCredential]$AdminCreds,\n\n        [Int]$RetryCount = 60,\n        [Int]$RetryIntervalSec = 5\n    ) \n    \n    Import-DscResource -ModuleName PSDesiredStateConfiguration\n    Import-DscResource -ModuleName xActiveDirectory -ModuleVersion 2.17.0.0\n    Import-DscResource -ModuleName xAdcsDeployment -ModuleVersion 1.4.0.0\n    Import-DscResource -ModuleName ADCSTemplate -ModuleVersion 1.0.1.0\n    \n    [System.Management.Automation.PSCredential]$DomainCreds = New-Object System.Management.Automation.PSCredential (\"$DomainName\\$($AdminCreds.UserName)\", $AdminCreds.Password)\n\n    Node $AllNodes.NodeName\n    {\n        LocalConfigurationManager\n        {\n            ActionAfterReboot = 'ContinueConfiguration'\n            ConfigurationMode = 'ApplyOnly'\n            RebootNodeIfNeeded = $true\n            AllowModuleOverWrite = $true\n        }\n\n        WindowsFeature ADDSInstall \n        { \n            Ensure = 'Present'\n            Name = 'AD-Domain-Services'\n        }  \n\n        WindowsFeature ADDSPowerShell\n        { \n            Ensure = 'Present' \n            Name = 'RSAT-AD-PowerShell'\n        }\n\n        # Optional GUI tools\n        WindowsFeature ADDSTools\n        { \n            Ensure = 'Present' \n            Name = 'RSAT-ADDS'\n        }\n\n        xADDomain FirstDS \n        {\n            DomainName = $DomainName\n            DomainAdministratorCredential = $DomainCreds\n            SafemodeAdministratorPassword = $DomainCreds\n            DomainNetbiosName = ($DomainName -split '\\.')[0]\n            DependsOn = \"[WindowsFeature]ADDSInstall\"\n        }\n<#\n        #This resource is broken as of 2.17.0.0.\n        #See Script resource alternative below.\n        #Revert to using this resource when it is fixed.\n\n        xWaitForADDomain DscForestWait\n        {\n            DomainName = $DomainName\n            DomainUserCredential = $DomainCreds\n            RetryCount = $RetryCount\n            RetryIntervalSec = $RetryIntervalSec\n            DependsOn = \"[xADDomain]FirstDS\"\n        } \n#>\n\n        Script xWaitForADDomain_Alternative\n        {\n            GetScript = {\n                Return @{\n                    Result = [string]$(([ADSI]\"LDAP://$Using:DomainName\").distinguishedName)\n                }\n            }\n            TestScript = {\n                $DN = \"DC=$($Using:DomainName -replace '\\.',',DC=')\"\n                $FoundDomain = $false\n                For ($i=1;$i -le $Using:RetryCount;$i++) {\n                    If (([ADSI]\"LDAP://$DN\").distinguishedName -eq $DN) {\n                        $FoundDomain = $true\n                        Write-Verbose \"Found domain $($Using:DomainName).\"\n                        break\n                    } Else {\n                        Write-Verbose \"Could not find domain $($Using:DomainName). Attempt $i/$($Using:RetryCount). Sleeping $($Using:RetryIntervalSec) seconds...\"\n                        Start-Sleep -Seconds $Using:RetryIntervalSec\n                    }\n                }\n                Return $FoundDomain\n            }\n            SetScript = {\n                Write-Verbose 'Cannot continue. Domain not found.'\n                Throw \"Could not find domain $($Using:DomainName).\"\n            }\n        }\n\n        xADRecycleBin RecycleBin\n        {\n           EnterpriseAdministratorCredential = $DomainCreds\n           ForestFQDN = $DomainName\n           #DependsOn = '[xWaitForADDomain]DscForestWait'\n           DependsOn = '[Script]xWaitForADDomain_Alternative'\n        }\n\n\n        ### OUs ###\n        $DomainRoot = \"DC=$($DomainName -replace '\\.',',DC=')\"\n        $DependsOn_OU = @()\n\n        ForEach ($RootOU in $ConfigurationData.NonNodeData.RootOUs) {\n\n            xADOrganizationalUnit \"OU_$RootOU\"\n            {\n                Name = $RootOU\n                Path = $DomainRoot\n                ProtectedFromAccidentalDeletion = $true\n                Description = \"OU for $RootOU\"\n                Credential = $DomainCred\n                Ensure = 'Present'\n                DependsOn = '[xADRecycleBin]RecycleBin'\n            }\n\n            ForEach ($ChildOU in $ConfigurationData.NonNodeData.ChildOUs) {\n                \n                xADOrganizationalUnit \"OU_$($RootOU)_$ChildOU\"\n                {\n                    Name = $ChildOU\n                    Path = \"OU=$RootOU,$DomainRoot\"\n                    ProtectedFromAccidentalDeletion = $true\n                    Credential = $DomainCred\n                    Ensure = 'Present'\n                    DependsOn = \"[xADOrganizationalUnit]OU_$RootOU\"\n                }\n\n                $DependsOn_OU += \"[xADOrganizationalUnit]OU_$($RootOU)_$ChildOU\"\n            }\n\n        }\n\n\n        ### USERS ###\n        # Use PasswordAuthentication = 'Negotiate' to avoid the password verification failure once ADCS is installed.\n        # https://github.com/PowerShell/xActiveDirectory/issues/61\n        $DependsOn_User = @()\n        $Users = $ConfigurationData.NonNodeData.UserData | ConvertFrom-CSV\n        ForEach ($User in $Users) {\n\n            xADUser \"NewADUser_$($User.UserName)\"\n            {\n                DomainName = $DomainName\n                Ensure = 'Present'\n                UserName = $User.UserName\n                Path = \"OU=Users,OU=$($User.Dept),$DomainRoot\"\n                Enabled = $true\n                PasswordAuthentication = 'Negotiate'\n                Password = New-Object -TypeName PSCredential -ArgumentList 'JustPassword', (ConvertTo-SecureString -String $User.Password -AsPlainText -Force)\n                DependsOn = $DependsOn_OU\n            }\n            $DependsOn_User += \"[xADUser]NewADUser_$($User.UserName)\"\n        }\n\n        ### GROUPS ###\n        ForEach ($RootOU in $ConfigurationData.NonNodeData.RootOUs) {\n            xADGroup \"NewADGroup_$RootOU\"\n            {\n                GroupName = \"G_$RootOU\"\n                GroupScope = 'Global'\n                Description = \"Global group for $RootOU\"\n                Category = 'Security'\n                Members = ($Users | Where-Object {$_.Dept -eq $RootOU}).UserName\n                Path = \"OU=Groups,OU=$RootOU,$DomainRoot\"\n                Ensure = 'Present'\n                DependsOn = $DependsOn_User\n            }\n        }\n\n\n        WindowsFeature ADCS-Cert-Authority\n        {\n            Ensure = 'Present'\n            Name = 'ADCS-Cert-Authority'\n            DependsOn = '[xADRecycleBin]RecycleBin'\n        }\n\n        WindowsFeature ADCS-Web-Enrollment\n        {\n            Ensure = 'Present'\n            Name = 'ADCS-Web-Enrollment'\n            DependsOn = '[xADRecycleBin]RecycleBin'\n        }\n\n        WindowsFeature RSAT-ADCS\n        {\n            Ensure = 'Present'\n            Name = 'RSAT-ADCS'\n            DependsOn = '[xADRecycleBin]RecycleBin'\n        }\n\n        xADCSCertificationAuthority ADCS\n        {\n            Ensure = 'Present'\n            Credential = $DomainCreds\n            CAType = 'EnterpriseRootCA'\n            DependsOn = '[WindowsFeature]ADCS-Cert-Authority'              \n        }\n\n        xADCSWebEnrollment CertSrv\n        {\n            IsSingleInstance = 'Yes'\n            Ensure = 'Present'\n            Credential = $DomainCreds\n            DependsOn = '[xADCSCertificationAuthority]ADCS'\n        }\n\n        ADCSTemplate PSDSCEncryptionTemplate\n        {\n            Ensure = 'Present'\n            DisplayName = 'PSCMS'\n            JSON = $ConfigurationData.NonNodeData.JSON_PSCMS\n            Publish = $true\n            Identity = \"$DomainName\\Domain Computers\", \"$DomainName\\Domain Controllers\"\n            AutoEnroll = $true\n            PsDscRunAsCredential = $DomainCreds\n            DependsOn = '[xADCSWebEnrollment]CertSrv'\n        }\n\n        ADCSTemplate TaniumTemplate\n        {\n            Ensure = 'Present'\n            DisplayName = 'Tanium'\n            JSON = $ConfigurationData.NonNodeData.JSON_Tanium\n            Publish = $true\n            Identity = \"$DomainName\\Domain Computers\"\n            AutoEnroll = $false\n            PsDscRunAsCredential = $DomainCreds\n            DependsOn = '[xADCSWebEnrollment]CertSrv'\n        }\n\n    }\n}\n\n\n$configData = @{\n    AllNodes = @(\n        @{\n            Nodename = \"localhost\"\n            PSDscAllowPlainTextPassword = $true\n            PSDscAllowDomainUser = $true\n            Credential = $cred\n        }\n    )\n    NonNodeData = @{\n        \n        UserData = @'\nUserName,Password,Dept\nTaniumAdmin,P@ssw0rd,Tanium\nTaniumService,P@ssw0rd,Tanium\n'@\n        RootOUs = 'Tanium'\n        ChildOUs = 'Users','Groups'\n\n        JSON_PSCMS = @'\n{\n    \"name\":  \"PowerShellCMS\",\n    \"displayName\":  \"PowerShellCMS\",\n    \"objectClass\":  \"pKICertificateTemplate\",\n    \"flags\":  131680,\n    \"revision\":  100,\n    \"msPKI-Cert-Template-OID\":  \"1.3.6.1.4.1.311.21.8.14606814.4579994.15679635.15482926.4928991.141.63412935.14964662\",\n    \"msPKI-Certificate-Application-Policy\":  [\n                                                 \"1.3.6.1.4.1.311.80.1\"\n                                             ],\n    \"msPKI-Certificate-Name-Flag\":  268435456,\n    \"msPKI-Enrollment-Flag\":  32,\n    \"msPKI-Minimal-Key-Size\":  2048,\n    \"msPKI-Private-Key-Flag\":  16842752,\n    \"msPKI-RA-Signature\":  0,\n    \"msPKI-Template-Minor-Revision\":  1,\n    \"msPKI-Template-Schema-Version\":  2,\n    \"pKICriticalExtensions\":  [\n                                  \"2.5.29.15\"\n                              ],\n    \"pKIDefaultCSPs\":  [\n                           \"1,Microsoft RSA SChannel Cryptographic Provider\"\n                       ],\n    \"pKIDefaultKeySpec\":  1,\n    \"pKIExpirationPeriod\":  [\n                                0,\n                                128,\n                                114,\n                                14,\n                                93,\n                                194,\n                                253,\n                                255\n                            ],\n    \"pKIExtendedKeyUsage\":  [\n                                \"1.3.6.1.4.1.311.80.1\"\n                            ],\n    \"pKIKeyUsage\":  [\n                        32\n                    ],\n    \"pKIMaxIssuingDepth\":  0,\n    \"pKIOverlapPeriod\":  [\n                             0,\n                             128,\n                             166,\n                             10,\n                             255,\n                             222,\n                             255,\n                             255\n                         ]\n}\n'@\n\n        JSON_Tanium = @'\n{\n    \"name\":  \"Tanium\",\n    \"displayName\":  \"Tanium\",\n    \"objectClass\":  \"pKICertificateTemplate\",\n    \"flags\":  131649,\n    \"revision\":  100,\n    \"msPKI-Cert-Template-OID\":  \"1.3.6.1.4.1.311.21.8.14606814.4579994.15679635.15482926.4928991.141.13175610.2217120\",\n    \"msPKI-Certificate-Application-Policy\":  [\n                                                 \"1.3.6.1.5.5.7.3.1\",\n                                                 \"1.3.6.1.5.5.7.3.2\"\n                                             ],\n    \"msPKI-Certificate-Name-Flag\":  1,\n    \"msPKI-Enrollment-Flag\":  0,\n    \"msPKI-Minimal-Key-Size\":  2048,\n    \"msPKI-Private-Key-Flag\":  16842768,\n    \"msPKI-RA-Signature\":  0,\n    \"msPKI-Template-Minor-Revision\":  2,\n    \"msPKI-Template-Schema-Version\":  2,\n    \"pKICriticalExtensions\":  [\n                                  \"2.5.29.7\",\n                                  \"2.5.29.15\"\n                              ],\n    \"pKIDefaultKeySpec\":  1,\n    \"pKIExpirationPeriod\":  [\n                                0,\n                                128,\n                                114,\n                                14,\n                                93,\n                                194,\n                                253,\n                                255\n                            ],\n    \"pKIExtendedKeyUsage\":  [\n                                \"1.3.6.1.5.5.7.3.1\",\n                                \"1.3.6.1.5.5.7.3.2\"\n                            ],\n    \"pKIKeyUsage\":  [\n                        160,\n                        0\n                    ],\n    \"pKIMaxIssuingDepth\":  0,\n    \"pKIOverlapPeriod\":  [\n                             0,\n                             128,\n                             166,\n                             10,\n                             255,\n                             222,\n                             255,\n                             255\n                         ]\n}\n'@\n    }\n}\n\n\n\n#Install-Module -Name xAdcsDeployment, xActiveDirectory -Force\n#Get-DscResource | Sort-Object ModuleName, Version, Name\n\nmd C:\\ADCS -ErrorAction SilentlyContinue\ncd C:\\ADCS\n\n$cred = New-Object -TypeName PSCredential -ArgumentList 'Administrator', (ConvertTo-SecureString -String 'Passw0rd' -AsPlainText -Force)\n\nCreateADDomainWithCS -ConfigurationData $configData -DomainName 'goatee.lab' -AdminCreds $cred\n\nSet-DscLocalConfigurationManager -Path .\\CreateADDomainWithCS -Verbose\nStart-DscConfiguration -Path .\\CreateADDomainWithCS -Force -Verbose -Wait\n\n\nbreak\n\n\n#region CERT REQUEST/INSTALL ##################################################\n\ndir Cert:\\LocalMachine\\My\ndir Cert:\\LocalMachine\\My | Select-Object Thumbprint,Subject,@{name='KeyUsage';expression={$_.Extensions.KeyUsages}} | fl *\n\ncertutil -pulse\n\n$Req = @{\n    Template          = 'PSCMS'\n    Url               = 'ldap:'\n    CertStoreLocation = 'Cert:\\LocalMachine\\My'\n}\nGet-Certificate @Req\n\ndir Cert:\\LocalMachine\\My | Select-Object Thumbprint,Subject,@{name='KeyUsage';expression={$_.Extensions.KeyUsages}} | fl *\n\n$DocEncrCert = (dir Cert:\\LocalMachine\\My -DocumentEncryptionCert)[-1]\nProtect-CmsMessage -To $DocEncrCert -Content \"Encrypted with my new cert from the new template!\"\n\n#endregion ####################################################################\n\n\n"
  },
  {
    "path": "ansible/roles/adcs_templates/files/ADCSTemplate/Examples/Demo.ps1",
    "content": "﻿break\r\n\r\nGet-Module -ListAvailable\r\nImport-Module ADCSTemplate\r\nGet-Command -Module ADCSTemplate\r\n\r\n# Manually open ADSIEDIT and show objects\r\nadsiedit.msc\r\n\r\n# Manually open MMC to build and browse an AD CS mgmt GUI\r\nmmc\r\n\r\nNew-ADCSDrive\r\ncd ADCS:\r\ndir\r\ncd '.\\CN=Certificate Templates'\r\ndir\r\ncd ..\r\ncd '.\\CN=Enrollment Services'\r\ndir\r\ncd c:\r\n\r\ncd \\\r\nmd ADCS\r\ncd ADCS\r\n\r\nGet-ADCSTemplate\r\nGet-ADCSTemplate | Sort-Object DisplayName | ft DisplayName\r\n\r\nExport-ADCSTemplate -DisplayName PSCMS\r\nExport-ADCSTemplate -DisplayName PSCMS > PSCMS.json\r\n\r\nNew-ADCSTemplate -DisplayName PSCMS2 -JSON (Get-Content .\\PSCMS.json -Raw) -Publish\r\n\r\nSet-ADCSTemplateACL -DisplayName PSCMS2 -Identity 'goatee\\domain computers' -Enroll -AutoEnroll\r\n(Get-ADCSTemplate pscms2).nTSecurityDescriptor.Access\r\n\r\nRemove-ADCSTemplate -DisplayName pscms2 -WhatIf\r\nRemove-ADCSTemplate -DisplayName pscms2\r\nRemove-ADCSTemplate -DisplayName Tanium\r\n"
  },
  {
    "path": "ansible/roles/adcs_templates/files/ADCSTemplate/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Ashley McGlone\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "ansible/roles/adcs_templates/files/ADCSTemplate/README.md",
    "content": "Find all code and samples at this location: [https://github.com/GoateePFE/ADCSTemplate/]()\n\n# ADCSTemplate\nA PowerShell module for exporting, importing, removing, permissioning, publishing Active Directory Certificate Templates.\nIt also includes a DSC resource for creating AD CS templates using these functions.\nThis was built with the intent of using DSC for rapid lab builds, \nbut it could also be used in production environments to move templates between AD CS environments.\n\n# Problem\nAren't you tired of using the Active Directory Certificate Services graphical interface to create and publish new certificate templates? Me too! I can build a domain controller and certificate server with DSC, but then I get stuck with manually creating the custom certificate templates for my environment. A popular example is the Document Encryption certificate used for DSC credential encryption and the CMS encryption cmdlets. You probably have some custom certificate templates unique to your company as well. No more right click, duplicate, permission, publish!\n\n# Solution\nThe ADCSTemplate module contains the following PowerShell functions:\n* Export-ADCSTemplate\n* Get-ADCSTemplate\n* New-ADCSDrive\n* New-ADCSTemplate\n* Remove-ADCSTemplate\n* Set-ADCSTemplateACL\n\nAnd the following DSC resource:\n* ADCSTemplate\n\n# Overview\nThis is a simple outline of the procedure to export and import your templates.\nYes, you must create it manually at least once.\n1. Create your desired template in the AD CS GUI.\n2. `Install-Module ADCSTemplate`\n3. `Export-ADCSTemplate -DisplayName foo > .\\foo.json`\n4. Copy the JSON file to your destination environment.\n5. `Install-Module ADCSTemplate`\n6. `New-ADCSTemplate -DisplayName foo2 -JSON (Get-Content .\\foo.json -Raw) -Publish -Identity Contoso\\MyGroup`\n7. -OR- Use the `ADCSTemplate` DSC Resource with the JSON string data to define the template. This is most easily accomplished using a ConfigurationData block to pass the large string. See the sample provided.\n\nIf you want to duplicate an existing template on the same server try this:\n\n```New-ADCSTemplate -DisplayName NewTemplateName -JSON (Export-ADCSTemplate -DisplayName OldTemplateName)```\n\nIf you want to export all templates try this:\n\n``` (Get-ADCSTemplate).name | ForEach-Object {\"Exporting $_\"; Export-ADCSTemplate -DisplayName $_ | Out-File .\\$_.json -Force}```\n\nSee the module function help texts for many clever use cases for this code, including a bonus function for creating a PSDrive to browse the objects in AD without using the GUI.\n\nSee the \\Examples directory for\n* `Demo.ps1` showing popular use cases of the functions together.\n* `Build-ADCS.ps1` DSC example for a full Active Directory domain controller build with Certificate Services and two sample templates.\n* `PowerShellCMS.json` a sample JSON output file you can use to create templates for PowerShell Cryptographic Message Syntax cmdlets and encryption credentials in DSC.\n\n# Requirements\n* PowerShell 5.x\n* Tested on Windows Server 2012 R2\n* Tested on Windows Server 2016 (issues with the xActiveDirectory module here, but the ADCSTemplate DSC works just fine)\n* Enterprise Administrator rights\n\n# Credits\nCreated by Ashley McGlone\n\n2017-2018\n\n[@GoateePFE](https://twitter.com/goateepfe)\n\n[http://aka.ms/goateepfe]()\n\n\n# Get-Help\n\n## Export-ADCSTemplate\n\n### Synopsis\nReturns a JSON string with the properties of an Active Directory certificate template.\n\n### Description\nReturns a JSON string with the properties of an Active Directory certificate template.\nBy default returns only the PKI-related properties of the object. These properties are\nsufficient for passing to the New-ADCSTemplate function.\n\n### Parameters\n\n-DisplayName <String>\n    DisplayName for the certificate to export.\n    \n    Required?                    true\n    Position?                    1\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    2\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Detailed [<SwitchParameter>]\n    Includes all ADObject properties of the template. These are not required for \n    use with the New-ADCSTemplate function.\n    \n    Required?                    false\n    Position?                    named\n    Default value                False\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nC.R.U.D. AD CS Template Operations in this module.\nNo longer have to use the cert GUI to clone a template and build a new one.\nCreate one manually the first time in the GUI, then export it to JSON.\nPass the JSON in your new environment (file, here string, DSC, etc.) to build from scratch.\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> Export-ADCSTemplate -DisplayName PowerShellCMS\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> Export-ADCSTemplate -DisplayName PowerShellCMS -Detailed\n\n```\n-------------------------- EXAMPLE 3 --------------------------\n\n```\nPS C:\\> ### Backup all the templates to JSON\nmd C:\\ADCSTemplates -ErrorAction SilentlyContinue\ncd C:\\ADCSTemplates\n(Get-ADCSTemplate).name | ForEach-Object {\"Exporting $_\"; Export-ADCSTemplate -DisplayName $_ | Out-File .\\$_.json -Force}\ndir\n\n```\n-------------------------- EXAMPLE 4 --------------------------\n\n```\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS-NEW -JSON (Export-ADCSTemplate -DisplayName PowerShellCMS-OLD)\n\n```\n\n## Get-ADCSTemplate\n\n### Synopsis\nReturns the properties of either a single or all Active Directory Certificate Template(s).\n\n### Description\nReturns the properties of either a single or list of Active Directory Certificate Template(s)\ndepending on whether a DisplayName parameter was passed.\n\n### Parameters\n\n-DisplayName <String>\n    Name of an AD CS template to retrieve.\n    \n    Required?                    false\n    Position?                    1\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    named\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> Get-ADCSTemplate\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> Get-ADCSTemplate -DisplayName PowerShellCMS\n\n```\n-------------------------- EXAMPLE 3 --------------------------\n\n```\nPS C:\\> Get-ADCSTemplate | Sort-Object Name | ft Name, Created, Modified\n\n```\n-------------------------- EXAMPLE 4 --------------------------\n\n```\nPS C:\\> ###View template permissions\n(Get-ADCSTemplate pscms).nTSecurityDescriptor\n(Get-ADCSTemplate pscms).nTSecurityDescriptor.Sddl\n(Get-ADCSTemplate pscms).nTSecurityDescriptor.Access\nConvertFrom-SddlString -Sddl (Get-ADCSTemplate pscms).nTSecurityDescriptor.sddl -Type ActiveDirectoryRights\n\n```\n\n## New-ADCSDrive\n\n### Synopsis\nMaps a PowerShell drive to the Active Directory Certificate Services location.\n\n### Description\nMaps a PowerShell drive to the Active Directory Certificate Services location \nof the Configuration partition under CN=Public Key Services,CN=Services,... .\nThe new drive is ADCS:. This is purely for convenience of checking the objects\nupdated by functions in the ADCSTemplate module.\n\n### Parameters\n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    1\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> New-ADCSDrive\nPS C:\\> Set-Location ADCS:\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> ### Explore templates with drive\nNew-ADCSDrive\nGet-PSDrive\ncd ADCS:\ndir\n\n# List templates\ncd '.\\CN=Certificate Templates'\ndir\ndir | fl *\ndir *WebServer*\n\n# list CAs\ncd \\\ncd '.\\CN=Enrollment Services'\ndir\ncd C:\n\n```\n\n## New-ADCSTemplate\n\n### Synopsis\nCreates a new Active Directory Certificate Services template based on a JSON export.\n\n### Description\nCreates a new Active Directory Certificate Services template based on a JSON export.\nOptionally can permission and publish the template (best practice).\n\n### Parameters\n\n-DisplayName <String>\n    DisplayName for the certificate template to create. This does not have to match\n    the original name of the exported template.\n    \n    Required?                    true\n    Position?                    1\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-JSON <String>\n    JSON string output from Export-ADCSTemplate. Defines the template to create.\n    Can be retrieved from file using Get-Content -Raw.\n    \n    Required?                    true\n    Position?                    2\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    3\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Identity <String[]>\n    String or string array of Active Directory identities (users or groups).\n    This is optional for permissioning the template.\n    \n    Required?                    false\n    Position?                    4\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-AutoEnroll [<SwitchParameter>]\n    Default permission is Read and Enroll. Use this switch to also grant AutoEnroll \n    to the identity. Only used when Identity parameter is used.\n    \n    Required?                    false\n    Position?                    named\n    Default value                False\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Publish [<SwitchParameter>]\n    Publish the template to *ALL* Certificate Authority issuers. Use with caution\n    in production environments. You may want to manually publish to only specific\n    Certificate Authorities in production. In a lab this is ideal.\n    \n    Required?                    false\n    Position?                    named\n    Default value                False\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nThis function does not use the official (complicated) API for PKI management.\nInstead it creates the exact same AD objects that are generated by the API,\nincluding AD forest-specific OIDs.\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS -JSON (Get-Content .\\pscms.json -Raw)\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS -JSON (Get-Content .\\pscms.json -Raw) -Server dc1.contoso.com -Identity G_DSCNodes -AutoEnroll -Publish\n# From a client configured for AD CS autoenrollment:\n$Req = @{\n    Template          = 'PowerShellCMS'\n    Url               = 'ldap:'\n    CertStoreLocation = 'Cert:\\LocalMachine\\My'\n}\nGet-Certificate @Req\n# Note: If you have the Carbon module installed, it conflicts with Get-Certificate native cmdlet.\n\n$DocEncrCert = (dir Cert:\\LocalMachine\\My -DocumentEncryptionCert | Sort-Object NotBefore)[-1]\nProtect-CmsMessage -To $DocEncrCert -Content \"Encrypted with my new cert from the new template!\"\n\n```\n-------------------------- EXAMPLE 3 --------------------------\n\n```\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS-NEW -JSON (Export-ADCSTemplate -DisplayName PowerShellCMS-OLD)\n\n```\n\n## Remove-ADCSTemplate\n\n### Synopsis\nRemoves a certificate template from Active Directory.\n\n### Description\nRemoves the template from any issuers where it is published.\nRemoves the template itself.\nRemoves the unique OID object of the template.\n\n### Parameters\n\n-DisplayName <String>\n    DisplayName for the certificate template to delete.\n    \n    Required?                    true\n    Position?                    1\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    2\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-WhatIf [<SwitchParameter>]\n    \n    Required?                    false\n    Position?                    named\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Confirm [<SwitchParameter>]\n    \n    Required?                    false\n    Position?                    named\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nUse with caution!\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> Remove-ADCSTemplate -DisplayName PowerShellCMS\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> (Get-ADCSTemplate).name | Where-Object {$_ -like \"PowerShellCMS*\"} | ForEach-Object {Remove-ADCSTemplate -DisplayName $_ -Verbose}\n\n```\n\n## Set-ADCSTemplateACL\n\n### Synopsis\nAdds an ACL to an Active Directory Certificate template.\n\n### Description\nAdds an ACL to an Active Directory Certificate template.\nDefault permission is read (without the Enroll or AutoEnroll switches).\n\n### Parameters\n\n-DisplayName <String>\n    Name of an AD CS template to receive the ACL.\n    \n    Required?                    true\n    Position?                    1\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    2\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Type <String>\n    ACL type: Allow or Deny\n    \n    Required?                    false\n    Position?                    3\n    Default value                Allow\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Identity <String[]>\n    String or string array of Active Directory identities (users or groups)\n    \n    Required?                    false\n    Position?                    4\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Enroll [<SwitchParameter>]\n    Set the Enroll permission\n    \n    Required?                    false\n    Position?                    named\n    Default value                False\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-AutoEnroll [<SwitchParameter>]\n    Set the AutoEnroll permission\n    \n    Required?                    false\n    Position?                    named\n    Default value                False\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Allow -Identity 'CONTOSO\\Servers Group' -Enroll\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Allow -Identity 'CONTOSO\\Servers Group','CONTOSO\\Workstations Group' -Enroll -AutoEnroll\n\n```\n-------------------------- EXAMPLE 3 --------------------------\n\n```\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Deny -Identity 'CONTOSO\\Servers Group'\n\n```\n"
  },
  {
    "path": "ansible/roles/adcs_templates/files/ESC13.json",
    "content": "{\n    \"name\":  \"ESC13\",\n    \"displayName\":  \"ESC13\",\n    \"objectClass\":  \"pKICertificateTemplate\",\n    \"flags\":  131616,\n    \"revision\":  100,\n    \"msPKI-Cert-Template-OID\":  \"1.3.6.1.4.1.311.21.8.16735922.7437492.10570883.2539024.15756463.185.9025784.11813639\",\n    \"msPKI-Certificate-Policy\": \"1.3.6.1.4.1.311.21.8.16735922.7437492.10570883.2539024.15756463.185.9025784.11813639\",\n    \"msPKI-Certificate-Application-Policy\":  [\n                                                 \"1.3.6.1.5.5.7.3.2\"\n                                             ],\n    \"msPKI-Certificate-Name-Flag\":  33554432,\n    \"msPKI-Enrollment-Flag\":  0,\n    \"msPKI-Minimal-Key-Size\":  2048,\n    \"msPKI-Private-Key-Flag\":  16842752,\n    \"msPKI-RA-Signature\":  0,\n    \"msPKI-Template-Minor-Revision\":  4,\n    \"msPKI-Template-Schema-Version\":  2,\n    \"pKICriticalExtensions\":  [\n                                  \"2.5.29.15\",\n                                  \"2.5.29.7\"\n                              ],\n    \"pKIDefaultCSPs\":  [\n                           \"3,Microsoft Base DSS Cryptographic Provider\",\n                           \"2,Microsoft Base Cryptographic Provider v1.0\",\n                           \"1,Microsoft Enhanced Cryptographic Provider v1.0\"\n                       ],\n    \"pKIDefaultKeySpec\":  2,\n    \"pKIExpirationPeriod\":  [\n                                0,\n                                64,\n                                57,\n                                135,\n                                46,\n                                225,\n                                254,\n                                255\n                            ],\n    \"pKIExtendedKeyUsage\":  [\n                                \"1.3.6.1.5.5.7.3.2\"\n                            ],\n    \"pKIKeyUsage\":  [\n                        128,\n                        0\n                    ],\n    \"pKIMaxIssuingDepth\":  0,\n    \"pKIOverlapPeriod\":  [\n                             0,\n                             128,\n                             166,\n                             10,\n                             255,\n                             222,\n                             255,\n                             255\n                         ]\n}\n"
  },
  {
    "path": "ansible/roles/adcs_templates/files/ESC9.json",
    "content": "{\n    \"name\":  \"ESC9\",\n    \"displayName\":  \"ESC9\",\n    \"objectClass\":  \"pKICertificateTemplate\",\n    \"flags\":  131642,\n    \"revision\":  100,\n    \"msPKI-Cert-Template-OID\":  \"1.3.6.1.4.1.311.21.8.12926314.13933278.9259679.1328214.12908673.21.15721773.8953759\",\n    \"msPKI-Certificate-Application-Policy\":  [\n                                                 \"1.3.6.1.4.1.311.10.3.4\",\n                                                 \"1.3.6.1.5.5.7.3.4\",\n                                                 \"1.3.6.1.5.5.7.3.2\"\n                                             ],\n    \"msPKI-Certificate-Name-Flag\":  33554432,\n    \"msPKI-Enrollment-Flag\":  524329,\n    \"msPKI-Minimal-Key-Size\":  2048,\n    \"msPKI-Private-Key-Flag\":  16842768,\n    \"msPKI-RA-Signature\":  0,\n    \"msPKI-Template-Minor-Revision\":  4,\n    \"msPKI-Template-Schema-Version\":  2,\n    \"pKICriticalExtensions\":  [\n                                  \"2.5.29.15\",\n                                  \"2.5.29.7\"\n                              ],\n    \"pKIDefaultCSPs\":  [\n                           \"1,Microsoft Enhanced Cryptographic Provider v1.0\"\n                       ],\n    \"pKIDefaultKeySpec\":  1,\n    \"pKIExpirationPeriod\":  [\n                                0,\n                                64,\n                                57,\n                                135,\n                                46,\n                                225,\n                                254,\n                                255\n                            ],\n    \"pKIExtendedKeyUsage\":  [\n                                \"1.3.6.1.4.1.311.10.3.4\",\n                                \"1.3.6.1.5.5.7.3.4\",\n                                \"1.3.6.1.5.5.7.3.2\"\n                            ],\n    \"pKIKeyUsage\":  [\n                        160,\n                        0\n                    ],\n    \"pKIMaxIssuingDepth\":  0,\n    \"pKIOverlapPeriod\":  [\n                             0,\n                             128,\n                             166,\n                             10,\n                             255,\n                             222,\n                             255,\n                             255\n                         ]\n}\n"
  },
  {
    "path": "ansible/roles/adcs_templates/tasks/main.yml",
    "content": "- name: Refresh\n  ansible.windows.win_command: gpupdate /force\n\n- name: Install ADCSTemplate Module\n  win_copy:\n    src: files/ADCSTemplate\n    dest: \"C:\\\\Program Files\\\\WindowsPowerShell\\\\Modules\"\n\n- name: create a directory for templates\n  win_file: \n    path: c:\\setup\n    state: directory\n\n- name: Copy templates json\n  win_copy:\n    src: \"files/{{item}}.json\"\n    dest: \"C:\\\\setup\\\\{{item}}.json\"\n  with_items:\n    - ESC1\n    - ESC2\n    - ESC3\n    - ESC3-CRA\n    - ESC4\n    - ESC9\n    - ESC13\n\n- name: Install templates\n  win_shell: |\n    if (-not(Get-ADCSTemplate -DisplayName \"{{item}}\")) { New-ADCSTemplate -DisplayName \"{{item}}\" -JSON (Get-Content c:\\setup\\{{item}}.json -Raw) -Identity \"{{domain_name}}\\Domain Users\" -Publish }\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    domain_name: \"{{domain}}\"\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  with_items:\n    - ESC1\n    - ESC2\n    - ESC3\n    - ESC3-CRA\n    - ESC4\n    - ESC9\n    - ESC13\n"
  },
  {
    "path": "ansible/roles/add_dns_record/tasks/main.yml",
    "content": "- name: Create a dns record\n  community.windows.win_dns_record:\n    name: \"{{record_name}}\"\n    type: \"{{record_type}}\"\n    values: \"{{record_value}}\"\n    zone: \"{{domain}}\""
  },
  {
    "path": "ansible/roles/child_domain/tasks/main.yml",
    "content": "- name: \"disable the registration of the {{nat_adapter}} interface (NAT address) in DNS\"\n  ansible.windows.win_shell: Get-NetAdapter '{{nat_adapter}}' | Set-DNSClient -RegisterThisConnectionsAddress $False\n  when: two_adapters\n\n- name: \"Set configure dns to {{dns_domain}}\"\n  win_dns_client:\n    adapter_names: \"{{domain_adapter}}\"\n    ipv4_addresses:\n      - \"{{hostvars[dns_domain].ansible_host}}\"\n    log_path: C:\\dns_log.txt\n\n- name: Install windows features - AD Domain Services\n  win_feature:\n    name: AD-Domain-Services\n    state: present\n    include_management_tools: yes\n  register: features\n\n- name: Install windows features - RSAT-ADDS\n  win_feature:\n    name: RSAT-ADDS\n    state: present\n    include_management_tools: yes\n  register: features\n\n# DNSCHANGE\n# - name: \"disable interface {{nat_adapter}} before join domain\"\n#   win_shell: netsh interface set interface \"{{nat_adapter}}\" disable\n\n- name: add child domain to parent domain\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $Password,\n\n          [String]\n          $DomainAdmin,\n\n          [String]\n          $ParentDomainName,\n\n          [String]\n          $NewDomainNetbiosName,\n\n          [String]\n          $ReplicationSourceDC,\n\n          [String]\n          $NewDomainName,\n\n          [String]\n          $DomSafePassword\n      )\n      try {\n          $child_domain = Get-ADDomain -Identity $NewDomainName\n          $domainExist=$true\n      } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {\n          $domainExist=$false\n      }\n      if (-not $domainExist) {\n        $Ansible.Changed = $true\n        $pass = ConvertTo-SecureString $Password -AsPlainText -Force\n        $Cred = New-Object System.Management.Automation.PSCredential ($DomainAdmin, $pass)\n        $safePassword = ConvertTo-SecureString $DomSafePassword -AsPlainText -Force\n        Install-ADDSDomain -Credential $Cred -SkipPreChecks -NewDomainName $NewDomainName -NewDomainNetbiosName $NewDomainNetbiosName -ParentDomainName $ParentDomainName -ReplicationSourceDC $ReplicationSourceDC -DatabasePath \"C:\\Windows\\NTDS\" -SYSVOLPath \"C:\\Windows\\SYSVOL\" -LogPath \"C:\\Windows\\Logs\" -SafeModeAdministratorPassword $safePassword -Force -NoRebootOnCompletion\n      } else {\n        $Ansible.Changed = $false\n      }\n    parameters:\n      Password: \"{{parent_domain_password}}\"\n      DomSafePassword: \"{{domain_password}}\"\n      DomainAdmin: \"{{parent_domain_user}}\"\n      ParentDomainName: \"{{parent_domain}}\"\n      ReplicationSourceDC: \"{{source_dc}}\"\n      NewDomainNetbiosName: \"{{netbios_name}}\"\n      NewDomainName: \"{{domain.split('.')[0]}}\"\n  register: child_result\n\n- name: Reboot\n  win_reboot:\n    reboot_timeout: 900\n    post_reboot_delay: 100\n  when: child_result.changed\n\n# - name: \"enable interface {{nat_adapter}} after domain joined\"\n#   win_shell: netsh interface set interface \"{{nat_adapter}}\" enable\n#   register: enable_interface\n#   until: \"enable_interface is not failed\"\n#   retries: 3\n#   delay: 120\n\n- name: enable the {{domain_adapter}} interface (local) for DNS client requests\n  ansible.windows.win_shell: dnscmd . /resetlistenaddresses {{ hostvars[dict_key].ansible_host }}\n  when: two_adapters\n\n- name: Check for xDnsServer Powershell module\n  win_psmodule:\n    name: xDnsServer\n    state: present\n\n# add external dns forwarder\n- name: Configure DNS Forwarders\n  win_dsc:\n    resource_name: xDnsServerForwarder\n    IsSingleInstance: \"yes\"\n    UseRootHint: false\n    IPAddresses:\n      - \"{{dns_server_forwarder}}\"\n\n- name: \"Install XactiveDirectory\"\n  win_psmodule:\n    name: ActiveDirectoryDSC\n    state: present\n\n# issue 156\n- name: enable the Active directory web services if not enabled\n  ansible.windows.win_shell: Set-Service -Name adws -StartupType Automatic\n"
  },
  {
    "path": "ansible/roles/common/tasks/chocolatey.yml",
    "content": "- name: Ensure chocolatey is installed\n  win_chocolatey:\n    name:\n    - chocolatey\n    - chocolatey-core.extension\n    state: present\n\n- name: Disable enhanced exit codes\n  win_chocolatey_feature:\n    name: useEnhancedExitCodes\n    state: disabled\n\n- name: Install multiple packages sequentially\n  win_chocolatey:\n    name: '{{ item }}'\n    state: present\n  with_items:\n  - notepadplusplus\n  - putty\n  - python\n  - git\n  - 7zip\n  - sysinternals\n  - wget\n  - pstools\n  ignore_errors: yes"
  },
  {
    "path": "ansible/roles/common/tasks/main.yml",
    "content": "- name: \"Force a DNS on the adapter {{nat_adapter}}\"\n  ansible.windows.win_dns_client:\n    adapter_names: \"{{nat_adapter}}\"\n    dns_servers: \n      - \"{{hostvars[dns_domain].ansible_host}}\"\n      - \"{{dns_server}}\"\n  when: force_dns_server == \"yes\"\n\n- name: Set a proxy for specific protocols\n  community.windows.win_http_proxy:\n    proxy:\n      http: \"{{ad_http_proxy}}\"\n      https: \"{{ad_https_proxy}}\"\n  when: http_proxy == \"yes\"\n\n- name: Configure IE to use a specific proxy per protocol\n  community.windows.win_inet_proxy:\n    proxy:\n      http: \"{{ad_http_proxy}}\"\n      https: \"{{ad_https_proxy}}\"\n  when: http_proxy == \"yes\"\n\n- name: Upgrade module PowerShellGet to fix accept license issue on last windows ansible version\n  win_shell: |\n    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12\n    Install-PackageProvider -Name NuGet -Force\n    Install-Module PowerShellGet -Force\n\n- name: Windows | Check for ComputerManagementDsc Powershell module\n  win_psmodule:\n    name: ComputerManagementDsc\n    state: present\n\n- name: Windows | Enable Remote Desktop\n  win_dsc:\n    resource_name: RemoteDesktopAdmin\n    IsSingleInstance : 'yes'\n    Ensure: present\n    UserAuthentication: Secure\n\n- name: Windows | Check for xNetworking Powershell module\n  win_psmodule:\n    name: xNetworking\n    state: present\n\n- name: Firewall | Allow RDP through Firewall\n  win_dsc:\n    resource_name: xFirewall\n    Name: \"Administrator access for RDP (TCP-In)\"\n    Ensure: present\n    Enabled: True\n    Profile: \"Domain\"\n    Direction: \"Inbound\"\n    Localport: \"3389\"\n    Protocol: \"TCP\"\n    Description: \"Opens the listener port for RDP\"\n\n- name: Add a network static route\n  community.windows.win_route:\n    destination: \"{{route_network}}\"\n    gateway: \"{{route_gateway}}\"\n    metric: 1\n    state: present\n  when: add_route == \"yes\"\n"
  },
  {
    "path": "ansible/roles/commonwkstn/tasks/main.yml",
    "content": "# DNSCHANGE\n- name: \"prioritize the {{domain_adapter}} interface (local) as the default for routing\"\n  ansible.windows.win_shell:\n    Set-NetIPInterface -InterfaceAlias \"{{domain_adapter}}\" -InterfaceMetric 10\n  when: two_adapters\n\n- name: \"Set configure dns to {{dns_domain}}\"\n  win_dns_client:\n    adapter_names: \"{{domain_adapter}}\"\n    ipv4_addresses:\n    - \"{{hostvars[dns_domain].ansible_host}}\"\n    log_path: C:\\dns_log.txt\n\n- name: \"Add workstation to {{member_domain}}\"\n  win_domain_membership:\n    dns_domain_name: \"{{member_domain}}\"\n    domain_admin_user: \"{{domain_username}}\"\n    domain_admin_password: \"{{domain_password}}\"\n#    domain_ou_path: \"{{member_domain_ou_path}}\"\n    state: domain\n  register: domain_state\n\n- name: Reboot if needed\n  win_reboot:    \n    reboot_timeout: 1500\n    post_reboot_delay: 100\n  when: domain_state.reboot_required\n\n"
  },
  {
    "path": "ansible/roles/dc_dns_conditional_forwarder/tasks/main.yml",
    "content": "- name: \"Add dns server zone\" \n  community.windows.win_dns_zone:\n    name: \"{{item}}\"\n    type: forwarder\n    replication: \"{{replication}}\"\n    dns_servers:\n      - \"{{hostvars[dc].ansible_host}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n    dc: \"{{lab.domains[item].dc}}\"\n  loop: \"{{ domains }}\"\n  when: item != domain and item != trust and item != parent_domain and '.'.join(item.split('.')[1:]) != domain\n\n# when not same domain, not parent or child and not already direct trusted domain"
  },
  {
    "path": "ansible/roles/dhcp/tasks/main.yml",
    "content": "# https://www.faqforge.com/windows/configure-dhcp-powershell/\n\n- name: Install DHCP\n  win_feature:\n    name: DHCP\n    state: present\n    include_management_tools: yes\n  register: win_feature\n\n- name: Reboot if installing windows feature requires it\n  ansible.windows.win_reboot:\n  when: win_feature.reboot_required\n\n- name: allow dhcp in dc\n  win_shell: |\n    Add-DHCPServerInDC -DNSName {{dc_fqdn}}\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n\n- name: Set dhcp scope\n  win_shell: |\n    $s = Get-DhcpServerv4Scope\n    if ($null -eq $s) {\n      Add-DhcpServerV4Scope -Name \"DHCP Scope\" -StartRange {{ip_from}} -EndRange {{ip_to}} -SubnetMask {{ip_mask}} -LeaseDuration {{lease_duration}}\n    }\n\n- name: Get default gateway\n  win_shell: |\n    (Get-NetRoute -DestinationPrefix \"0.0.0.0/0\").NextHop\n  register: ip_gateway_command\n\n- name: Set ip_gateway\n  set_fact:\n    ip_gateway: \"{{ ip_gateway_command.stdout | trim }}\"\n\n- name: Add DNS Server and Default Gateway Options in DHCP\n  win_shell: |\n    Set-DhcpServerV4OptionValue -DnsServer {{dns_ip}} -Router {{ip_gateway}}\n\n#- name: create server option boot server hostname (MECM)\n#  win_shell: |\n#    Set-DhcpServerV4OptionValue -OptionId 66 -Value {{sccm_server}}\n#\n#- name: create boot file name (SMSBoot\\x64\\wdsnbp.com)\n#  win_shell: |\n#    Set-DhcpServerV4OptionValue -OptionId 67 -Value \"SMSBoot\\x64\\wdsnbp.com\"\n\n# https://www.systemsitpro.com/2017/12/how-to-configure-dhcp-for-pxe-booting.html\n# https://www.it-connect.fr/serveurs-dhcp-wds-boot-pxe-bios-et-uefi/\n# Add-DhcpServerv4OptionDefinition -ComputerName SRV-ADDS-01 -Name PXEClient -Description \"PXE Support\" -OptionId 060 -Type String\n- name: Restart service DHCP\n  win_service:\n    name: 'dhcpserver'\n    state: restarted"
  },
  {
    "path": "ansible/roles/disable_user/tasks/main.yml",
    "content": "- name: \"Disable the user {{username}}\"\n  ansible.windows.win_user:\n    name: \"{{username}}\"\n    account_disabled: true\n"
  },
  {
    "path": "ansible/roles/dns_conditional_forwarder/tasks/main.yml",
    "content": "- name: Add dns server zone\n  community.windows.win_dns_zone:\n    name: \"{{zone_name}}\"\n    type: forwarder\n    replication: \"{{replication}}\"\n    dns_servers:\n      - \"{{master_server}}\""
  },
  {
    "path": "ansible/roles/domain_controller/tasks/main.yml",
    "content": "# DNSCHANGE\n# - name: \"disable interface {{nat_adapter}} before join domain\"\n#   win_shell: netsh interface set interface \"{{nat_adapter}}\" disable\n\n- name: \"disable the registration of the {{nat_adapter}} interface (NAT address) in DNS\"\n  ansible.windows.win_shell:\n    Get-NetAdapter '{{nat_adapter}}' | Set-DNSClient -RegisterThisConnectionsAddress $False\n  when: two_adapters\n\n- name: Ensure that domain exists\n  win_domain:\n    domain_netbios_name: \"{{netbios_name}}\"\n    dns_domain_name: \"{{domain}}\"\n    safe_mode_password: \"{{domain_password}}\"\n  register: check_domain\n\n- name: Reboot to complete domain creation\n  win_reboot:\n    reboot_timeout: 900\n    post_reboot_delay: 300\n  when: check_domain.changed\n\n- name: Ensure the server is a domain controller\n  win_domain_controller:\n    dns_domain_name: \"{{domain}}\"\n    domain_admin_user: \"{{domain_username}}\"\n    domain_admin_password: \"{{domain_password}}\"\n    safe_mode_password: \"{{domain_password}}\"\n    state: domain_controller\n  register: check_domain_controller\n\n- name: Reboot to complete domain controller setup\n  win_reboot:\n    reboot_timeout: 900\n    post_reboot_delay: 100\n  when: check_domain_controller.changed\n\n# DNSCHANGE\n# - name: \"enable interface {{nat_adapter}} after domain joined\"\n#   win_shell: netsh interface set interface \"{{nat_adapter}}\" enable\n#   register: enable_interface_dc\n#   until: \"enable_interface_dc is not failed\"\n#   retries: 3\n#   delay: 120\n\n- name: Be sure DNS feature is installed\n  win_feature:\n    name: DNS\n    state: present\n\n- name: Check for xDnsServer Powershell module\n  win_psmodule:\n    name: xDnsServer\n    state: present\n\n- name: enable only the {{domain_adapter}} interface (local) for DNS client requests\n  ansible.windows.win_shell: dnscmd . /resetlistenaddresses {{ hostvars[dict_key].ansible_host }}\n  when: two_adapters\n\n- name: Configure DNS Forwarders\n  win_dsc:\n    resource_name: xDnsServerForwarder\n    IsSingleInstance: \"yes\"\n    UseRootHint: false\n    IPAddresses:\n      - \"{{dns_server_forwarder}}\"\n\n#- name: install nuget\n#  win_shell: install-packageprovider -name nuget -force\n\n- name: \"Install XactiveDirectory\"\n  win_psmodule:\n    name: ActiveDirectoryDSC\n    state: present\n\n- name: Ensure Administrator is part of Enterprise Admins\n  win_domain_group_membership:\n    name: \"Enterprise Admins\"\n    members:\n      - Administrator\n    state: present\n\n- name: Ensure Administrator is part of Domain Admins\n  win_domain_group_membership:\n    name: \"Domain Admins\"\n    members:\n      - Administrator\n    state: present\n"
  },
  {
    "path": "ansible/roles/domain_controller_slave/tasks/main.yml",
    "content": "- name: Set configure dns\n  win_dns_client:\n    adapter_names: \"{{domain_adapter}}\"\n    ipv4_addresses:\n    - \"{{hostvars[dns_domain].ansible_host}}\"\n    log_path: C:\\dns_log.txt\n\n- name: Promote the server to aditionnal DC\n  win_domain_controller:\n    dns_domain_name: \"{{domain_name}}\"\n    domain_admin_user: \"{{domain_username}}\"\n    domain_admin_password: \"{{domain_password}}\"\n    safe_mode_password: \"{{domain_password}}\"\n    state: domain_controller\n    log_path: C:\\ansible_win_domain_controller.txt\n  register: check_domain_controller\n\n- name: Reboot to complete domain controller setup\n  win_reboot:\n    reboot_timeout: 600\n    post_reboot_delay: 30\n  when: check_domain_controller.changed\n"
  },
  {
    "path": "ansible/roles/elk/defaults/main.yml",
    "content": "elasticsearch_version: '7.x'\nes_cluster_name: elasticsearch"
  },
  {
    "path": "ansible/roles/elk/files/elasticsearch.yml",
    "content": "# ======================== Elasticsearch Configuration =========================\n#\n# NOTE: Elasticsearch comes with reasonable defaults for most settings.\n#       Before you set out to tweak and tune the configuration, make sure you\n#       understand what are you trying to accomplish and the consequences.\n#\n# The primary way of configuring a node is via this file. This template lists\n# the most important settings you may want to configure for a production cluster.\n#\n# Please consult the documentation for further information on configuration options:\n# https://www.elastic.co/guide/en/elasticsearch/reference/index.html\n#\n# ---------------------------------- Cluster -----------------------------------\n#\n# Use a descriptive name for your cluster:\n#\n#cluster.name: my-application\n#\n# ------------------------------------ Node ------------------------------------\n#\n# Use a descriptive name for the node:\n#\n#node.name: node-1\n#\n# Add custom attributes to the node:\n#\n#node.attr.rack: r1\n#\n# ----------------------------------- Paths ------------------------------------\n#\n# Path to directory where to store the data (separate multiple locations by comma):\n#\npath.data: /var/lib/elasticsearch\n#\n# Path to log files:\n#\npath.logs: /var/log/elasticsearch\n#\n# ----------------------------------- Memory -----------------------------------\n#\n# Lock the memory on startup:\n#\n#bootstrap.memory_lock: true\n#\n# Make sure that the heap size is set to about half the memory available\n# on the system and that the owner of the process is allowed to use this\n# limit.\n#\n# Elasticsearch performs poorly when the system is swapping the memory.\n#\n# ---------------------------------- Network -----------------------------------\n#\n# Set the bind address to a specific IP (IPv4 or IPv6):\n#\nnetwork.host: 0.0.0.0\n#\n# Set a custom port for HTTP:\n#\nhttp.port: 9200\n#\n# For more information, consult the network module documentation.\n#\n# --------------------------------- Discovery ----------------------------------\n#\n# Pass an initial list of hosts to perform discovery when this node is started:\n# The default list of hosts is [\"127.0.0.1\", \"[::1]\"]\n#\n#discovery.seed_hosts: [\"host1\", \"host2\"]\ndiscovery.type: single-node\n#\n# Bootstrap the cluster using an initial set of master-eligible nodes:\n#\n#cluster.initial_master_nodes: [\"node-1\", \"node-2\"]\n#\n# For more information, consult the discovery and cluster formation module documentation.\n#\n# ---------------------------------- Gateway -----------------------------------\n#\n# Block initial recovery after a full cluster restart until N nodes are started:\n#\n#gateway.recover_after_nodes: 3\n#\n# For more information, consult the gateway module documentation.\n#\n# ---------------------------------- Various -----------------------------------\n#\n# Require explicit names when deleting indices:\n#\n#action.destructive_requires_name: true\n"
  },
  {
    "path": "ansible/roles/elk/files/kibana.yml",
    "content": "# Kibana is served by a back end server. This setting specifies the port to use.\nserver.port: 5601\n\n# Specifies the address to which the Kibana server will bind. IP addresses and host names are both valid values.\n# The default is 'localhost', which usually means remote machines will not be able to connect.\n# To allow connections from remote users, set this parameter to a non-loopback address.\nserver.host: \"0.0.0.0\"\n\n# Enables you to specify a path to mount Kibana at if you are running behind a proxy.\n# Use the `server.rewriteBasePath` setting to tell Kibana if it should remove the basePath\n# from requests it receives, and to prevent a deprecation warning at startup.\n# This setting cannot end in a slash.\n#server.basePath: \"\"\n\n# Specifies whether Kibana should rewrite requests that are prefixed with\n# `server.basePath` or require that they are rewritten by your reverse proxy.\n# This setting was effectively always `false` before Kibana 6.3 and will\n# default to `true` starting in Kibana 7.0.\n#server.rewriteBasePath: false\n\n# Specifies the public URL at which Kibana is available for end users. If\n# `server.basePath` is configured this URL should end with the same basePath.\n#server.publicBaseUrl: \"\"\n\n# The maximum payload size in bytes for incoming server requests.\n#server.maxPayloadBytes: 1048576\n\n# The Kibana server's name.  This is used for display purposes.\n#server.name: \"your-hostname\"\n\n# The URLs of the Elasticsearch instances to use for all your queries.\n#elasticsearch.hosts: [\"http://localhost:9200\"]\n\n# Kibana uses an index in Elasticsearch to store saved searches, visualizations and\n# dashboards. Kibana creates a new index if the index doesn't already exist.\n#kibana.index: \".kibana\"\n\n# The default application to load.\n#kibana.defaultAppId: \"home\"\n\n# If your Elasticsearch is protected with basic authentication, these settings provide\n# the username and password that the Kibana server uses to perform maintenance on the Kibana\n# index at startup. Your Kibana users still need to authenticate with Elasticsearch, which\n# is proxied through the Kibana server.\n#elasticsearch.username: \"kibana_system\"\n#elasticsearch.password: \"pass\"\n\n# Enables SSL and paths to the PEM-format SSL certificate and SSL key files, respectively.\n# These settings enable SSL for outgoing requests from the Kibana server to the browser.\n#server.ssl.enabled: false\n#server.ssl.certificate: /path/to/your/server.crt\n#server.ssl.key: /path/to/your/server.key\n\n# Optional settings that provide the paths to the PEM-format SSL certificate and key files.\n# These files are used to verify the identity of Kibana to Elasticsearch and are required when\n# xpack.security.http.ssl.client_authentication in Elasticsearch is set to required.\n#elasticsearch.ssl.certificate: /path/to/your/client.crt\n#elasticsearch.ssl.key: /path/to/your/client.key\n\n# Optional setting that enables you to specify a path to the PEM file for the certificate\n# authority for your Elasticsearch instance.\n#elasticsearch.ssl.certificateAuthorities: [ \"/path/to/your/CA.pem\" ]\n\n# To disregard the validity of SSL certificates, change this setting's value to 'none'.\n#elasticsearch.ssl.verificationMode: full\n\n# Time in milliseconds to wait for Elasticsearch to respond to pings. Defaults to the value of\n# the elasticsearch.requestTimeout setting.\n#elasticsearch.pingTimeout: 1500\n\n# Time in milliseconds to wait for responses from the back end or Elasticsearch. This value\n# must be a positive integer.\n#elasticsearch.requestTimeout: 30000\n\n# List of Kibana client-side headers to send to Elasticsearch. To send *no* client-side\n# headers, set this value to [] (an empty list).\n#elasticsearch.requestHeadersWhitelist: [ authorization ]\n\n# Header names and values that are sent to Elasticsearch. Any custom headers cannot be overwritten\n# by client-side headers, regardless of the elasticsearch.requestHeadersWhitelist configuration.\n#elasticsearch.customHeaders: {}\n\n# Time in milliseconds for Elasticsearch to wait for responses from shards. Set to 0 to disable.\n#elasticsearch.shardTimeout: 30000\n\n# Logs queries sent to Elasticsearch. Requires logging.verbose set to true.\n#elasticsearch.logQueries: false\n\n# Specifies the path where Kibana creates the process ID file.\n#pid.file: /run/kibana/kibana.pid\n\n# Enables you to specify a file where Kibana stores log output.\n#logging.dest: stdout\n\n# Set the value of this setting to true to suppress all logging output.\n#logging.silent: false\n\n# Set the value of this setting to true to suppress all logging output other than error messages.\n#logging.quiet: false\n\n# Set the value of this setting to true to log all events, including system usage information\n# and all requests.\n#logging.verbose: false\n\n# Set the interval in milliseconds to sample system and process performance\n# metrics. Minimum is 100ms. Defaults to 5000.\n#ops.interval: 5000\n\n# Specifies locale to be used for all localizable strings, dates and number formats.\n# Supported languages are the following: English - en , by default , Chinese - zh-CN .\n#i18n.locale: \"en\"\n"
  },
  {
    "path": "ansible/roles/elk/tasks/main.yml",
    "content": "- name: \"Update cache\"\n  apt:\n    update_cache: true\n    cache_valid_time: 86400\n\n- name: Add required dependencies.\n  apt:\n    name:\n      - apt-transport-https\n      - gnupg2\n    state: present\n    update_cache: yes\n\n- name: Add Elasticsearch apt key.\n  apt_key:\n    url: https://artifacts.elastic.co/GPG-KEY-elasticsearch\n    state: present\n\n- name: Add Elasticsearch repository.\n  apt_repository:\n    repo: 'deb https://artifacts.elastic.co/packages/{{ elasticsearch_version }}/apt stable main'\n    state: present\n    update_cache: true\n\n- name: Install logstash\n  apt:\n    name: logstash\n    state: present\n\n- name: Install java\n  apt:\n    name: openjdk-11-jre\n    state: present\n\n- name: Install elasticsearch\n  apt:\n    name: elasticsearch\n    state: present\n\n- name: Install kibana\n  apt:\n    name: kibana\n    state: present\n\n- name: copy kibana config\n  copy:\n    src: kibana.yml\n    dest: /etc/kibana/kibana.yml\n    owner: \"root\"\n    group: \"kibana\"\n    mode: 0660\n\n- name: elasticsearch change start timeout to 3min\n  lineinfile:\n    destfile: /usr/lib/systemd/system/elasticsearch.service\n    regexp: 'TimeoutStartSec='\n    line: 'TimeoutStartSec=180'\n\n- name: copy elasticsearch config\n  copy:\n    src: elasticsearch.yml\n    dest: /etc/elasticsearch/elasticsearch.yml\n    owner: \"root\"\n    group: \"elasticsearch\"\n    mode: 0660\n\n- name: enable logstash\n  service:\n    name: logstash\n    enabled: yes\n\n- name: enable elasticsearch\n  service:\n    name: elasticsearch\n    enabled: yes\n\n- name: enable kibana\n  service:\n    name: kibana\n    enabled: yes\n\n- name: start logstash\n  service:\n    name: logstash\n    state: started\n\n- name: start elasticsearch\n  service:\n    name: elasticsearch\n    state: started\n\n- name: start kibana\n  service:\n    name: kibana\n    state: started\n"
  },
  {
    "path": "ansible/roles/enable_user/tasks/main.yml",
    "content": "- name: \"Enable the user {{username}}\"\n  ansible.windows.win_user:\n    name: \"{{username}}\"\n    account_disabled: false\n"
  },
  {
    "path": "ansible/roles/fix_dns/tasks/main.yml",
    "content": "# ONE INTERFACE\n# nat adapter == domain adapter => DC and next web\n- name: \"Change DNS on the adapter {{nat_adapter}}\"\n  ansible.windows.win_dns_client:\n    adapter_names: \"{{nat_adapter}}\"\n    dns_servers:\n      - \"{{hostvars[dns_domain].ansible_host}}\"\n      - \"{{dns_server}}\"\n  when: force_dns_server == \"yes\" and not two_adapters\n\n- name: \"Change DNS on the adapter {{nat_adapter}}\"\n  ansible.windows.win_dns_client:\n    adapter_names: \"{{nat_adapter}}\"\n    dns_servers:\n      - \"{{hostvars[dns_domain].ansible_host}}\"\n      - \"{{dns_server_forwarder}}\"\n  when: force_dns_server != \"yes\" and not two_adapters\n\n\n# TWO INTERFACES\n# domain adapter => dc\n# nat adapter => web\n- name: \"Change DNS on the adapter {{nat_adapter}}\"\n  ansible.windows.win_dns_client:\n    adapter_names: \"{{nat_adapter}}\"\n    dns_servers:\n      - \"{{dns_server}}\"\n  when: force_dns_server == \"yes\" and two_adapters\n\n- name: \"Change DNS on the adapter {{nat_adapter}}\"\n  ansible.windows.win_dns_client:\n    adapter_names: \"{{nat_adapter}}\"\n    dns_servers:\n      - \"{{dns_server_forwarder}}\"\n  when: force_dns_server != \"yes\" and two_adapters\n\n- name: \"Change DNS on the adapter {{domain_adapter}}\"\n  ansible.windows.win_dns_client:\n    adapter_names: \"{{domain_adapter}}\"\n    dns_servers:\n      - \"{{hostvars[dns_domain].ansible_host}}\"\n  when: two_adapters"
  },
  {
    "path": "ansible/roles/gmsa/tasks/main.yml",
    "content": "# $gMSA_Name = 'gmsaWWW'\n# $gMSA_FQDN = 'gmsaWWW.contoso.com'\n# $gMSA_SPNs = 'http/www', 'http/www.contoso.com'\n# $gMSA_HostNames = 'webServer01', 'webServer02', 'webServer03'\n\n- name: Create GMSA Account\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $gMSA_Name,\n\n          [String]\n          $gMSA_FQDN,\n\n          [String[]]\n          $gMSA_SPNs,\n\n          [String[]]\n          $gMSA_HostNames\n      )\n      Import-Module ActiveDirectory\n      Set-Location AD:\n      Add-KDSRootKey -EffectiveTime (Get-Date).AddHours(-10)\n      $gMSA_HostsGroup = $gMSA_HostNames | ForEach-Object { Get-ADComputer -Identity $_ }\n      New-ADServiceAccount -Name $gMSA_Name -DNSHostName $gMSA_FQDN -PrincipalsAllowedToRetrieveManagedPassword $gMSA_HostsGroup -ServicePrincipalNames $gMSA_SPNs\n    parameters:\n      gMSA_Name: \"{{item.value.gMSA_Name}}\"\n      gMSA_FQDN: \"{{item.value.gMSA_FQDN}}\"\n      gMSA_SPNs: \"{{item.value.gMSA_SPNs}}\"\n      gMSA_HostNames: \"{{item.value.gMSA_HostNames}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  with_dict: \"{{ ad_gmsa }}\"\n"
  },
  {
    "path": "ansible/roles/gmsa_hosts/tasks/main.yml",
    "content": "- name: Install-WindowsFeature RSAT-AD-PowerShell\n  ansible.windows.win_feature:\n    name: RSAT-AD-PowerShell \n    state: present\n  when: \"hostname in item.value.gMSA_HostNames\"\n  with_dict: \"{{ ad_gmsa }}\"\n\n- name: Install ADServiceAccount\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n        param (\n          [String]\n          $gMSA_Name\n      )\n      Install-ADServiceAccount -Identity $gMSA_Name\n    parameters:\n        gMSA_Name: \"{{item.value.gMSA_Name}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  when: \"hostname in item.value.gMSA_HostNames\"\n  with_dict: \"{{ ad_gmsa }}\""
  },
  {
    "path": "ansible/roles/groups_domains/tasks/main.yml",
    "content": "- name: \"Reboot and wait for the AD system to restart\"\n  win_reboot:\n    test_command: \"Get-ADUser -Identity Administrator -Properties *\"\n    post_reboot_delay: 100\n\n- name: \"synchronizes all domains\"\n  win_shell: repadmin /syncall /Ade\n  become: yes\n  become_method: runas\n  become_user: \"{{domain_username}}\"\n  vars:\n    ansible_become_pass: \"{{domain_password}}\"\n\n- name: \"Add a domain user/group from another Domain in the multi-domain forest to a domain group : {{domain_server}}\"\n  community.windows.win_domain_group_membership:\n    domain_server: \"{{domain_server}}\"\n    domain_username: \"{{domain_username}}\"\n    domain_password: \"{{domain_password}}\"\n    name: \"{{item.key}}\"\n    members: \"{{ item.value }}\"\n    state: Present\n  with_dict: \"{{ domain_groups_members }}\"\n  register: group_membership\n  until: \"group_membership is not failed\"\n  retries: 3\n  delay: 60\n"
  },
  {
    "path": "ansible/roles/iis/files/index.html",
    "content": "<html>\n    <head>\n    </head>\n    <body>\n        <p>GOAD SAMPLE PAGE</p>\n    </body>\n</html>"
  },
  {
    "path": "ansible/roles/iis/tasks/main.yml",
    "content": "- name: Enable update service\n  ansible.windows.win_service:\n    name: Windows Update\n    state: started\n    start_mode: auto\n\n- name: Install IIS Management Features\n  win_feature:\n    name: Web-Mgmt-Tools, \n          Web-Mgmt-Console, \n          Web-Scripting-Tools, \n          Web-Mgmt-Service\n    state: present\n\n- name: Add SYSTEM allow rights to machine keys (required for installation of IIS 6 components)\n  win_acl:\n    path: C:\\ProgramData\\Microsoft\\Crypto\\RSA\\MachineKeys\\\n    user: SYSTEM\n    rights: FullControl\n    type: allow\n    state: present\n    inherit: ContainerInherit, ObjectInherit\n    propagation: 'InheritOnly'\n\n- name: Install IIS 6 Compatibility Features \n  win_feature:\n    name: Web-Mgmt-Compat,\n          Web-Metabase,\n          Web-Lgcy-Mgmt-Console,\n          Web-Lgcy-Scripting,\n          Web-WMI\n    state: present\n\n- name: Install IIS Web-Server with sub features and management tools\n  win_feature:\n    name: Web-Server\n    state: present\n    include_sub_features: yes\n    include_management_tools: yes\n  register: win_feature\n\n- name: Create directory\n  win_file:\n    path: C:\\\\inetpub\n    state: directory\n\n- name: Create directory\n  win_file:\n    path: C:\\\\inetpub\\\\wwwroot\n    state: directory\n\n- name: default-website-index\n  win_copy:\n    src: files/index.html\n    dest: \"C:\\\\inetpub\\\\wwwroot\\\\index.html\"\n\n- name: Reboot if installing Web-Server feature requires it\n  ansible.windows.win_reboot:\n  when: win_feature.reboot_required\n\n"
  },
  {
    "path": "ansible/roles/keepass/defaults/main.yml",
    "content": "keepass_url_install_package: https://unlimited.dl.sourceforge.net/project/keepass/KeePass 2.x/2.60/KeePass-2.60-Setup.exe?viasf=1\nkeepass_download_location: c:\\\\setup\nkeepass_install_bin: \"{{keepass_download_location}}\\\\\\\\KeePass-2.60-Setup.exe\"\n"
  },
  {
    "path": "ansible/roles/keepass/tasks/main.yml",
    "content": "- name: check keepass already exist\n  win_stat:\n    path: C:\\Program Files\\KeePass Password Safe 2\\KeePass.exe\n  register: keepass_install\n\n- name: Create keepass_download_location folder if not exist\n  ansible.windows.win_file:\n    path: \"{{keepass_download_location}}\"\n    state: directory\n  when: not keepass_install.stat.exists\n\n- name: \"Download Keepass to {{keepass_install_bin}}\"\n  ansible.windows.win_get_url:\n    url: \"{{ keepass_url_install_package }}\"\n    dest: \"{{keepass_install_bin}}\"\n  when: not keepass_install.stat.exists\n\n- name: Install Keepass\n  win_command: \"{{ keepass_install_bin }} /VERYSILENT\"\n  when: not keepass_install.stat.exists\n"
  },
  {
    "path": "ansible/roles/klink/defaults/main.yml",
    "content": "putty_dir: \"C:\\\\Program Files\\\\PuTTY\"\nklink_url: \"https://www.9bis.net/kitty/files/klink.exe\"\nklink_path: \"{{ putty_dir }}\\\\klink.exe\""
  },
  {
    "path": "ansible/roles/klink/tasks/main.yml",
    "content": "---\n# Ensure PuTTY installation directory exists\n- name: Create PuTTY directory\n  ansible.windows.win_file:\n    path: \"{{ putty_dir }}\"\n    state: directory\n\n# Check if klink.exe already exists\n- name: Check if klink.exe is already installed\n  ansible.windows.win_stat:\n    path: \"{{ klink_path }}\"\n  register: klink_stat\n\n# Download klink.exe only if it is missing\n- name: Download klink.exe (only if not present)\n  ansible.windows.win_get_url:\n    url: \"{{ klink_url }}\"\n    dest: \"{{ klink_path }}\"\n  when: not klink_stat.stat.exists\n\n# Verify klink availability (non-fatal check)\n- name: Check klink version\n  ansible.windows.win_command: '\"C:\\Program Files\\PuTTY\\klink.exe\" -V'\n  register: klink_version\n  changed_when: false\n  failed_when: false\n\n# Display detected klink version\n- name: Show klink version\n  debug:\n    var: klink_version.stdout"
  },
  {
    "path": "ansible/roles/laps/dc/defaults/main.yml",
    "content": "---\nmove_computer: False\nprep_servers: False\napply_dacl: False\ncreate_gpo: False\ngpo_linked: False\ninstall_servers: False\ntest_deployment: False"
  },
  {
    "path": "ansible/roles/laps/dc/files/comment.cmtx",
    "content": "<?xml version='1.0' encoding='utf-8'?>\n<policyComments xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" revision=\"1.0\" schemaVersion=\"1.0\" xmlns=\"http://www.microsoft.com/GroupPolicy/CommentDefinitions\">\n  <policyNamespaces>\n    <using prefix=\"ns0\" namespace=\"FullArmor.Policies.C9E1D975_EA58_48C3_958E_3BC214D89A2E\"></using>\n  </policyNamespaces>\n  <comments>\n    <admTemplate></admTemplate>\n  </comments>\n  <resources minRequiredRevision=\"1.0\">\n    <stringTable></stringTable>\n  </resources>\n</policyComments>"
  },
  {
    "path": "ansible/roles/laps/dc/library/win_ad_dacl.ps1",
    "content": "#!powershell\n\n# Copyright: (c) 2018, Jordan Borean\n# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)\n\n#Requires -Module Ansible.ModuleUtils.Legacy\n#Requires -Module Ansible.ModuleUtils.SID\n\n$ErrorActionPreference = \"Stop\"\n\n$params = Parse-Args -arguments $args -supports_check_mode $true\n$check_mode = Get-AnsibleParam -obj $params -name \"_ansible_check_mode\" -type \"bool\" -default $false\n\n$path = Get-AnsibleParam -obj $params -name \"path\" -type \"str\" -failifempty $true\n$aces = Get-AnsibleParam -obj $params -name \"aces\" -type \"list\" -failifempty $true\n$state = Get-AnsibleParam -obj $params -name \"state\" -type \"str\" -default \"present\" -validateset \"absent\", \"present\"\n\n$result = @{\n    changed = $false\n}\n\nImport-Module -Name ActiveDirectory\n\n$common_ad_parameters = @{}\n\nFunction ConvertTo-SchemaGuid {\n    param(\n        [Parameter(Mandatory=$true)]$Value,\n        [Parameter(Mandatory=$true)][String]$Name,\n        [Parameter(Mandatory=$true)][Int32]$Entry,\n        [Hashtable]$CommonParameters\n    )\n\n    if ($null -eq $Value.$Name) {\n        return [System.Guid]::Empty\n    }\n    $raw_value = $Value.$Name\n\n    try {\n        $guid = [System.Guid]::Parse($raw_value)\n        return $guid\n    } catch [System.FormatException] {}  # not a GUID, we try and convert by scanning AD\n\n    $root_schema = (Get-ADRootDSE @CommonParameters).schemaNamingContext\n    $id_object = Get-ADObject -Filter { Name -eq $raw_value } -SearchBase $root_schema -Property schemaIDGUID @CommonParameters\n    if ($null -eq $id_object) {\n        Fail-Json -obj $result -message \"Failed to convert ace entry option $Entry $Name to object guid '$($raw_value)'\"\n    } else {\n        $schema_guid = New-Object -TypeName System.Guid -ArgumentList @(,$id_object.schemaIDGUID)\n        return $schema_guid\n    }\n}\n\n# Convert the input ace entries to a format we can compare against the real ACEs\n$valid_access_rights = [System.Enum]::GetNames([System.DirectoryServices.ActiveDirectoryRights])\n$valid_inheritance_types = [System.Enum]::GetNames([System.DirectoryServices.ActiveDirectorySecurityInheritance])\n\n$raw_aces = [System.Collections.ArrayList]@()\nforeach ($ace in $aces) {\n    $identity_sid_str = Convert-ToSID -account_name $ace.account\n\n    if ($null -eq $ace.rights) {\n        $msg = \"Found undefined ace entry index $($raw_aces.Count) rights. Valid options $($valid_access_rights -join \", \")\"\n        Fail-Json -obj $result -message $msg\n    }\n    $ace_rights = $ace.rights\n    if ($ace_rights -isnot [Array]) {\n        $ace_rights = $ace_rights.ToString().Split(\",\").Trim()\n    }\n\n    foreach ($ace_right in $ace_rights) {\n        if ($ace_right -notin $valid_access_rights) {\n            $msg = \"Invalid value for ace entry index $(raw_aces.Count) rights, '$ace_right'. Valid options $($valid_access_rights -join \", \")\"\n            Fail-Json -obj $result -message $msg\n        }\n    }\n    $ace_rights = [System.Enum]::Parse([System.DirectoryServices.ActiveDirectoryRights], $ace_rights -join \", \", $true)\n\n    $access = switch($ace.access) {\n        \"allow\" { [System.Security.AccessControl.AccessControlType]::Allow }\n        \"deny\" { [System.Security.AccessControl.AccessControlType]::Deny }\n        default { Fail-Json -obj $result -message \"Invalid value for ace entry index $($raw_aces.Count) access, '$access'. Valid options allow, deny\" }\n    }\n\n    if ($ace.inheritance_type -notin $valid_inheritance_types) {\n        $msg = \"Invalid value for ace entry index $($raw_aces.Count) inheritance_type, '$($ace.inheritance_type)'. Valid options $($valid_inheritance_types -join \", \")\"\n        Fail-Json -obj $result -message $msg\n    }\n    $inheritance_type = [System.DirectoryServices.ActiveDirectorySecurityInheritance]$ace.inheritance_type\n\n    $object_type = ConvertTo-SchemaGuid -Value $ace `\n        -Name \"object_type\" -Entry $raw_aces.Length `\n        -CommonParameters $common_ad_parameters\n\n    $inherited_object_type = ConvertTo-SchemaGuid -Value $ace `\n        -Name \"inherited_object_type\" -Entry $raw_aces.Count `\n        -CommonParameters $common_ad_parameters\n\n    $raw_ace = New-Object -TypeName System.DirectoryServices.ActiveDirectoryAccessRule -ArgumentList @(\n        (New-Object -TypeName System.Security.Principal.SecurityIdentifier -ArgumentList $identity_sid_str),\n        $ace_rights,\n        $access,\n        $object_type,\n        $inheritance_type\n        $inherited_object_type\n    )\n    $raw_aces.Add($raw_ace) > $null\n}\n\n# Now get the actual DACL for the AD object specified\n$ad_object = Get-ADObject -Identity $path -Properties nTSecurityDescriptor @common_ad_parameters\n\n$actual_sd = $ad_object.nTSecurityDescriptor\n$actual_dacl = $actual_sd.GetAccessRules($true, $false, [System.Security.Principal.SecurityIdentifier])\n$comparison_props = @(\n    \"ActiveDirectoryRights\",\n    \"InheritanceType\",\n    \"ObjectType\",\n    \"InheritedObjectType\",\n    \"AccessControlType\",\n    \"IdentityReference\"\n)\n\nforeach ($raw_ace in $raw_aces) {\n    $found_ace = $null\n\n    foreach ($actual_ace in $actual_dacl) {\n        $mismatched = $false\n        foreach ($comparison_prop in $comparison_props) {\n            if ($actual_ace.$comparison_prop -ne $raw_ace.$comparison_prop) {\n                $mismatched = $true\n                break\n            }\n        }\n        if (-not $mismatched) {\n            $found_ace = $actual_ace\n            break\n        }\n    }\n\n    if ($state -eq \"absent\" -and $null -ne $found_ace) {\n        $ad_object.nTSecurityDescriptor.RemoveAccessRuleSpecific($found_ace)\n        $result.changed = $true\n    } elseif ($state -eq \"present\" -and $null -eq $found_ace) {\n        $ad_object.nTSecurityDescriptor.AddAccessRule($raw_ace)\n        $result.changed = $true\n    }\n}\n\nif ($result.changed -eq $true) {\n    $replacements = @{\n        nTSecurityDescriptor = $ad_object.nTSecurityDescriptor\n    }\n    Set-ADObject -Identity $ad_object.ObjectGUID -Replace $replacements -WhatIf:$check_mode @common_ad_parameters\n}\n\nExit-Json -obj $result"
  },
  {
    "path": "ansible/roles/laps/dc/library/win_ad_object.ps1",
    "content": "#!powershell\n\n# Copyright: (c) 2018, Jordan Borean\n# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)\n\n#Requires -Module Ansible.ModuleUtils.Legacy\n\n$ErrorActionPreference = \"Stop\"\n\n$params = Parse-Args -arguments $args -supports_check_mode $true\n$check_mode = Get-AnsibleParam -obj $params -name \"_ansible_check_mode\" -type \"bool\" -default $false\n\n$attributes = Get-AnsibleParam -obj $params -name \"attributes\"\n$context = Get-AnsibleParam -obj $params -name \"context\" -type \"str\" -default \"default\" -validateset \"configuration\", \"default\", \"root_domain\", \"schema\"\n# $domain_server = Get-AnsibleParam -obj $params -name \"domain_server\" -type \"str\"\n# $domain_username = Get-AnsibleParam -obj $params -name \"domain_username\" -type \"str\"\n# $domain_password = Get-AnsibleParam -obj $params -name \"domain_password\" -type \"str\" -failifempty ($null -ne $domain_username)\n$may_contain = Get-AnsibleParam -obj $params -name \"may_contain\" -type \"list\"\n$name = Get-AnsibleParam -obj $params -name \"name\" -type \"str\" -failifempty $true\n$type = Get-AnsibleParam -obj $params -name \"type\" -type \"str\" -default \"attribute\" -validateset \"attribute\", \"class\"\n$update_schema = Get-AnsibleParam -obj $params -name \"update_schema\" -type \"bool\" -default $false\n\n$result = @{\n    changed = $false\n}\n\nImport-Module -Name ActiveDirectory\n\n$common_params = @{}\n# if ($null -ne $domain_server) {\n#     $common_params.Server = $domain_server\n# }\n# if ($null -ne $domain_username) {\n#     $sec_pass = ConvertTo-SecureString -String $domain_password -AsPlainText -Force\n#     $common_params.Credential = (New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $domain_username, $sec_pass)\n# }\n\n$root_dse = Get-ADRootDSE -Properties schemaNamingContext, rootDomainNamingContext @common_params\n$context = switch($context) {\n    \"configuration\" { $root_dse.configurationNamingContext }\n    \"default\" { $root_dse.defaultNamingContext }\n    \"root_domain\" { $root_dse.rootDomainNamingContext }\n    \"schema\" { $root_dse.schemaNamingContext }\n}\n\ntry {\n    $search_filter = { DistinguishedName -eq $name -or ldapDisplayName -eq $name }\n    $existing_obj = Get-ADObject -SearchBase $context -Filter $search_filter -Properties * @common_params\n} catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {\n    $existing_obj = $null\n}\n\nif ($null -eq $existing_obj) {\n    $ldap_type = switch ($type) {\n        \"attribute\" { \"attributeSchema\" }\n        \"class\" { \"classSchema\" }\n    }\n    New-ADObject -Name $name -Path $context -OtherAttributes $attributes `\n        -Type $ldap_type -WhatIf:$check_mode @common_params\n    $result.changed = $true\n} elseif ($null -ne $attributes) {\n    # Compare the input attributes with the existing attributes and change if required\n    $replacements = @{}\n    $additions = @{}\n    $clear = [System.Collections.Generic.List`1[String]]@()\n\n    foreach ($attribute_entry in $attributes.GetEnumerator()) {\n        $attribute_key = $attribute_entry.Key\n        $attribute_value = $attribute_entry.Value\n\n        $existing_value = $existing_obj.$attribute_key\n        if ($null -eq $attribute_value -and $null -ne $existing_value) {\n            $clear.Add($attribute_key) > $null\n        } elseif ($null -ne $attribute_value -and $null -eq $existing_value) {\n            $additions.$attribute_key = $attribute_value\n        } elseif ($attribute_value -ne $existing_value) {\n            $replacements.$attribute_key = $attribute_value\n        }\n    }\n\n    if ($replacements.Count -gt 0 -or $additions.Count -gt 0 -or $clear.Count -gt 0) {\n        $set_params = $common_params.Clone()\n        if ($replacements.Count -gt 0) {\n            $set_params.Replace = $replacements\n        }\n        if ($additions.Count -gt 0) {\n            $set_params.Add = $additions\n        }\n        if ($clear.Count -gt 0) {\n            $set_params.Clear = $clear.ToArray()\n        }\n\n        Set-ADObject -Identity $existing_obj.ObjectGuid @set_params\n        $result.changed = $true\n    }\n}\n\n# Now set the mayContain attributes, we do a last check on existing_obj in case we are in check mode\nif ($null -ne $may_contain -and $null -ne $existing_obj) {\n    foreach ($may_contain_entry in $may_contain) {\n        if (-not $existing_obj.mayContain.Contains($may_contain_entry)) {\n            Set-ADObject -Identity $existing_obj.ObjectGuid -Add @{ mayContain = $may_contain_entry } @common_params > $null\n            $result.changed = $true\n        }\n    }\n}\n\n# Reload the schema cache if a change occurred\nif ($result.changed -and $update_schema) {\n    $ctor_args = [System.Collections.Generic.List`1[String]]@(\"LDAP://$($root_dse.dnsHostName)/RootDSE\")\n    if ($null -ne $domain_username) {\n        $ctor_args.Add($domain_username) > $null\n        $ctor_args.Add($domain_password) > $null\n    }\n    $dse = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList $ctor_args.ToArray()\n    try {\n        $dse.Put(\"SchemaUpdateNow\", 1)\n        if (-not $check_mode) {\n            $dse.SetInfo()\n        }\n    } finally {\n        $dse.Dispose()\n    }\n}\n\nExit-Json -obj $result\n\n"
  },
  {
    "path": "ansible/roles/laps/dc/library/win_gpo.ps1",
    "content": "#!powershell\n\n# Copyright: (c) 2018, Jordan Borean\n# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)\n\n#Requires -Module Ansible.ModuleUtils.Legacy\n\n$ErrorActionPreference = \"Stop\"\n\n$params = Parse-Args -arguments $args -supports_check_mode $true\n$check_mode = Get-AnsibleParam -obj $params -name \"_ansible_check_mode\" -type \"bool\" -default $false\n\n$description = Get-AnsibleParam -obj $params -name \"description\" -type \"str\"\n$name = Get-AnsibleParam -obj $params -name \"name\" -type \"str\" -failifempty $true\n$state = Get-AnsibleParam -obj $params -name \"state\" -type \"str\" -default \"present\" -validateset \"absent\", \"present\"\n\n$result = @{\n    changed = $false\n}\n\n$gpo = Get-GPO -Name $name -ErrorAction SilentlyContinue\nif ($state -eq \"absent\" -and $null -ne $gpo) {\n    $result.id = $gpo.Id\n    $result.path = $gpo.Path\n    $gpo | Remove-GPO -WhatIf:$check_mode\n    $result.changed = $true\n} elseif ($state -eq \"present\") {\n    if ($null -eq $gpo) {\n        $new_params = @{\n            Name = $name\n            WhatIf = $check_mode\n        }\n        if ($null -ne $description) {\n            $new_params.Comment = $description\n        }\n        $gpo = New-GPO @new_params\n        $result.changed = $true\n    }\n\n    # When creating a GPO in check mode these values won't be set\n    if ($null -ne $gpo) {\n        $result.id = $gpo.Id\n        $result.path = $gpo.Path\n    } else {\n        $result.id = [System.Guid]::Empty.ToString()\n        $result.path = \"cn=$($result.id),cn=policies,cn=system,dc=check,dc=domain\"\n    }\n}\n\nExit-Json -obj $result"
  },
  {
    "path": "ansible/roles/laps/dc/library/win_gpo_link.ps1",
    "content": "#!powershell\n\n# Copyright: (c) 2018, Jordan Borean\n# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)\n\n#Requires -Module Ansible.ModuleUtils.Legacy\n\n$ErrorActionPreference = \"Stop\"\n\n$params = Parse-Args -arguments $args -supports_check_mode $true\n$check_mode = Get-AnsibleParam -obj $params -name \"_ansible_check_mode\" -type \"bool\" -default $false\n\n$name = Get-AnsibleParam -obj $params -name \"name\" -type \"str\" -failifempty $true\n$state = Get-AnsibleParam -obj $params -name \"state\" -type \"str\" -default \"present\" -ValidateSet \"absent\", \"present\"\n$enforced = Get-AnsibleParam -obj $params -name \"enforced\" -type \"bool\"\n$enabled = Get-AnsibleParam -obj $params -name \"enabled\" -type \"bool\"\n$target = Get-AnsibleParam -obj $params -name \"target\" -type \"str\"\n\nif (-not $target) {\n    $target = (Get-ADRootDSE).defaultNamingContext\n}\n\n$result = @{\n    changed = $false\n}\n\n$link = (Get-GPInheritance -Target $target).GpoLinks | Where-Object { $_.DisplayName -eq $name }\nif ($state -eq \"present\") {\n    if (-not $link) {\n        $link = New-GPLink -Name $name -Target $target -WhatIf:$check_mode\n        $result.changed = $true\n    }\n\n    if ($null -ne $enabled -and $link.Enabled -ne $enabled) {\n        $enabled_value = if ($enabled) { \"Yes\" } else { \"No\" }\n        $link = $link | Set-GPLink -LinkEnabled $enabled_value -WhatIf:$check_mode\n        $result.changed = $true\n    }\n    if ($null -ne $enforced -and $link.Enforced -ne $enforced) {\n        $enforced_value = if ($enforced) { \"Yes\" } else { \"No\" }\n        $link = $link | Set-GPLink -Enforced $enforced_value -WhatIf:$check_mode\n        $result.changed = $true\n    }\n} else {\n    if ($link) {\n        $link | Remove-GPLink -WhatIf:$check_mode\n        $result.changed = $true\n    }\n}\n\nExit-Json -obj $result\n\n"
  },
  {
    "path": "ansible/roles/laps/dc/library/win_gpo_reg.ps1",
    "content": "#!powershell\n\n# Copyright: (c) 2018, Jordan Borean\n# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)\n\n#Requires -Module Ansible.ModuleUtils.Legacy\n\n$ErrorActionPreference = \"Stop\"\n\n$params = Parse-Args -arguments $args -supports_check_mode $true\n$check_mode = Get-AnsibleParam -obj $params -name \"_ansible_check_mode\" -type \"bool\" -default $false\n$diff = Get-AnsibleParam -obj $params -name \"_ansible_diff\" -type \"bool\" -default $false\n\n$gpo = Get-AnsibleParam -obj $params -name \"gpo\" -type \"str\" -failifempty $true\n$name = Get-AnsibleParam -obj $params -name \"name\" -type \"str\" -failifempty $true\n$path = Get-AnsibleParam -obj $params -name \"path\" -type \"str\" -failifempty $true\n$state = Get-AnsibleParam -obj $params -name \"state\" -type \"str\" -default \"present\" -validateset \"absent\", \"disabled\", \"present\"\n$type = Get-AnsibleParam -obj $params -name \"type\" -type \"str\" -default \"string\" -ValidateSet \"string\", \"expandstring\", \"binary\", \"dword\", \"multistring\", \"qword\"\n$value = Get-AnsibleParam -obj $params -name \"value\"\n\n$result = @{\n    changed = $false\n}\nif ($diff) {\n    $result.diff = @{\n        before = \"\"\n        after = \"\"\n    }\n}\n\nif ($state -in @(\"absent\", \"disabled\") -and $null -ne $value) {\n    Fail-Json -obj $result -message \"Cannot set a value with state=$state\"\n}\n\nFunction Convert-RegExportHexStringToByteArray {\n    <#\n    .SYNOPSIS\n    Simplified version of Convert-HexStringToByteArray from\n    https://cyber-defense.sans.org/blog/2010/02/11/powershell-byte-array-hex-convert\n    Expects a hex in the format you get when you run reg.exe export and\n    converts to a byte array so powershell can modify binary registry entries\n\n    .PARAMETER String\n    The string to convert in the format hex:be,ef,be,ef,be,ef,be,ef,be,ef\n    #>#\n    param(\n        [Parameter(Mandatory=$true)][String]$String\n    )\n    # Remove 'hex:' from the front of the string if present\n    $String = $String.ToLower() -replace '^hex\\:',''\n\n    # Remove whitespace and any other non-hex crud.\n    $String = $String -replace '[^a-f0-9\\\\,x\\-\\:]',''\n\n    # Turn commas into colons\n    $String = $String -replace ',',':'\n\n    # Maybe there's nothing left over to convert...\n    if ($String.Length -eq 0) {\n        return ,@()\n    }\n\n    # Split string with or without colon delimiters.\n    if ($String.Length -eq 1) {\n        return ,@([System.Convert]::ToByte($String,16))\n    } elseif (($String.Length % 2 -eq 0) -and ($String.IndexOf(\":\") -eq -1)) {\n        return ,@($String -split '([a-f0-9]{2})' | ForEach-Object { if ($_) {[System.Convert]::ToByte($_,16)}})\n    } elseif ($String.IndexOf(\":\") -ne -1) {\n        return ,@($String -split ':+' | ForEach-Object {[System.Convert]::ToByte($_,16)})\n    } else {\n        return ,@()\n    }\n}\n\nFunction Get-DiffValueString {\n    <#\n    .SYNOPSIS\n    Converts an input value to a string for use in a diff comparison.\n\n    .PARAMETER Type\n    The registry value type that is used to display the appropriate string\n    output.\n\n    .PARAMETER Value\n    The value to stringify.\n    #>\n    param(\n        [Parameter(Mandatory=$true)]\n        [ValidateSet(\"string\", \"expandstring\", \"binary\", \"dword\", \"multistring\", \"qword\")]\n        [String]$Type,\n        [Parameter(Mandatory=$true)]$Value\n    )\n    if ($Type -eq \"binary\") {\n        $hex_values = [System.Collections.ArrayList]@()\n        foreach ($dec_value in $Value) {\n            $hex_values.Add(\"0x$(\"{0:x2}\" -f $dec_value)\") > $null\n        }\n        $diff_value = \"[$($hex_values -join \", \")]\"\n    } elseif ($Type -eq \"dword\") {\n        $diff_value = \"0x$(\"{0:x8}\" -f $Value)\"\n    } elseif ($Type -eq \"qword\") {\n        $diff_value = \"0x$(\"{0:x16}\" -f $Value)\"\n    } elseif ($Type -eq \"multistring\") {\n        $diff_value = \"[$($Value -join \", \")]\"\n    } else {\n        if ($Value.EndsWith([char]0x0000)) {\n            $Value = $Value.Substring(0, $Value.Length - 1)\n        }\n\n        $diff_value = $Value\n    }\n\n    return $diff_value\n}\n\n# Convert the input value to the type specified\nif ($type -eq \"binary\") {\n    if ($null -eq $value) {\n        $value = \"\"\n    }\n\n    if ($value -is [String]) {\n        $value = [byte[]](Convert-RegExportHexStringToByteArray -String $value)\n    } elseif ($value -is [Int]) {\n        if ($value -gt 255) {\n            Fail-Json -obj $result -message \"Cannot convert binary value '$value' to byte array, please specify this value as a yaml byte array or comma separated hex value string\"\n        }\n        $value = [byte[]]@([byte]$value)\n    } elseif ($value -is [Array]) {\n        $value = [byte[]]$value\n    }\n} elseif ($type -in @(\"dword\", \"qword\")) {\n    # dword's and dword's don't allow null values, set to 0\n    if ($null -eq $value) {\n        $value = 0\n    }\n\n    if ($value -is [String]) {\n        # If the value is a string we need to convert it to an unsigned int64\n        # it needs to be unsigned as Ansible passes in an unsigned value while\n        # powershell uses a signed value type. The value will then be converted\n        # below\n        $value = [UInt64]$value\n    }\n\n    if ($type -eq \"dword\") {\n        if ($value -gt [UInt32]::MaxValue) {\n            Fail-Json -obj $result -message \"value cannot be larger than 0xffffffff when type is dword\"\n        } elseif ($value -gt [Int32]::MaxValue) {\n            # When dealing with larger int32 (> 2147483647 or 0x7FFFFFFF) PowerShell\n            # automatically converts it to a signed int64. We need to convert this to\n            # signed int32 by parsing the hex string value.\n            $value = \"0x$(\"{0:x}\" -f $value)\"\n        }\n        $value = [Int32]$value\n    } else {\n        if ($value -gt [UInt64]::MaxValue) {\n            Fail-Json -obj $result -message \"value cannot be larger than 0xffffffffffffffff when type is qword\"\n        } elseif ($value -gt [Int64]::MaxValue) {\n            $value = \"0x$(\"{0:x}\" -f $value)\"\n        }\n        $value = [Int64]$value\n    }\n} elseif ($type -in @(\"string\", \"expandstring\")) {\n    # A null string or expandstring must be empty quotes\n    if ($null -eq $value) {\n        $value = \"\"\n    }\n} elseif ($type -eq \"multistring\") {\n    # Convert the value for a multistring to a String[] array\n    if ($null -eq $value) {\n        $value = [String[]]@()\n    } elseif ($value -isnot [Array]) {\n        $new_value = New-Object -TypeName String[] -ArgumentList 1\n        $new_value[0] = $value.ToString([CultureInfo]::InvariantCulture)\n        $value = $new_value\n    } else {\n        $new_value = New-Object -TypeName String[] -ArgumentList $value.Count\n        foreach ($entry in $value) {\n            $new_value[$value.IndexOf($entry)] = $entry.ToString([CultureInfo]::InvariantCulture)\n        }\n        $value = $new_value\n    }\n}\n\n$existing_value = Get-GPRegistryValue -Name $gpo -Key $path -ValueName $name -ErrorAction SilentlyContinue\nif ($null -ne $existing_value -and $diff) {\n    $result.diff.before = @{\n        disabled = ($existing_value.PolicyState -eq \"Delete\")\n        gpo = $gpo\n        name = $existing_value.ValueName\n        path = $existing_value.KeyPath\n        type = $existing_value.Type.ToString()\n        value = (Get-DiffValueString -Type $existing_value.Type.ToString() -Value $existing_value.Value)\n    }\n}\n\nif ($state -eq \"absent\") {\n    if ($null -ne $existing_value) {\n        Remove-GPRegistryValue -Name $gpo -Key $path -ValueName $name -WhatIf:$check_mode > $null\n        $result.changed = $true\n    }\n} else {\n    $common_params = @{\n        Name = $gpo\n        Key = $path\n        ValueName = $name\n        WhatIf = $check_mode\n    }\n\n    if ($null -eq $existing_value) {\n        if ($state -eq \"disabled\") {\n            $common_params.Disable = $true\n        } else {\n            $common_params.Value = $value\n            $common_params.Type = $type\n        }\n\n        Set-GPRegistryValue @common_params > $null\n        $result.changed = $true\n    } elseif ($state -eq \"disabled\") {\n        if ($existing_value.PolicyState -ne \"Delete\") {\n            Set-GPRegistryValue -Disable @common_params > $null\n            $result.changed = $true\n        }\n    } elseif ($existing_value.PolicyState -eq \"Delete\") {\n        # If the previous state was disabled then we need to remove that value\n        # before we set the new one as it will cause double ups on the key\n        Remove-GPRegistryValue @common_params > $null\n        Set-GPRegistryValue -Value $value -Type $type @common_params > $null\n        $result.changed = $true\n    } else {\n        $before_type = $existing_value.Type.ToString()\n        $before_value = Get-DiffValueString -Type $before_type -Value $existing_value.Value\n        $new_value = Get-DiffValueString -Type $type -Value $value\n\n        if (($before_value -ne $new_value) -or ($before_type -ne $type)) {\n            Set-GPRegistryValue -Value $value -Type $type @common_params > $null\n            $result.changed = $true\n        }\n    }\n\n    if ($diff) {\n        if ($check_mode) {\n            # in check mode we won't have access to the new values so just used the inputs\n            $result.diff.after = @{\n                disabled = ($state -eq \"disabled\")\n                gpo = $gpo\n                name = $name\n                path = $path\n                type = $type\n                value = (Get-DiffValueString -Type $type -Value $value)\n            }\n        } else {\n            $new_value = Get-GPRegistryValue -Name $gpo -Key $path -ValueName $name\n            $result.diff.after = @{\n                disabled = ($new_value.PolicyState -eq \"Delete\")\n                gpo = $gpo\n                name = $new_value.ValueName\n                path = $new_value.KeyPath\n                type = $new_value.Type.ToString()\n                value = (Get-DiffValueString -Type $new_value.Type.ToString() -Value $new_value.Value)\n            }\n        }\n    }\n}\n\nExit-Json -obj $result\n\n"
  },
  {
    "path": "ansible/roles/laps/dc/tasks/install.yml",
    "content": "---\n- name: \"Create Laps OU if not exist\"\n  win_dsc:\n    resource_name: ADOrganizationalUnit\n    name: \"{{ laps_path.split(',')[0].split('=')[1] }}\"\n    path:  \"{{ ','.join(laps_path.split(',')[1:]) }}\"\n\n- name: Install LAPS Package on Servers\n  ansible.windows.win_package:\n    arguments: \"ADDLOCAL=Management.PS,Management.ADMX ALLUSERS=1 /qn\"\n    path: https://download.microsoft.com/download/C/7/A/C7AAD914-A8A6-4904-88A1-29E657445D03/LAPS.x64.msi\n    state: present\n    creates_path: \"%ProgramFiles%\\\\LAPS\"\n  register: pri_laps_install\n  until: pri_laps_install is success\n  retries: 3  # Try 3 times just in case it failed to download the URL\n  delay: 1\n\n- name: Reboot After Installing LAPS on Servers\n  ansible.windows.win_reboot:\n    reboot_timeout: 900\n    post_reboot_delay: 100\n  when: pri_laps_install.reboot_required\n\n- name: Configure Password Properties\n  win_ad_object:\n    name: ms-Mcs-AdmPwd\n    attributes:\n      adminDescription: LAPS Password Attribute\n      lDAPDisplayName: ms-Mcs-AdmPwd\n      adminDisplayName: ms-Mcs-AdmPwd\n      attributeId: 1.2.840.113556.1.8000.2554.50051.45980.28112.18903.35903.6685103.1224907.2.1\n      attributeSyntax: '2.5.5.5'  # String(IAS)\n      omSyntax: 19  # String(Printable)\n      isSingleValued: True\n      systemOnly: False\n      isMemberOfPartialAttributeSet: False\n      searchFlags: 904  # RO,NV,CF,PR - http://www.frickelsoft.net/blog/?p=151\n      showInAdvancedViewOnly: False\n    context: schema\n    type: attribute\n    update_schema: True\n  # privileges required to update the schema attributes\n  register: passwordprop\n  until: \"passwordprop is not failed\"\n  retries: 3\n  delay: 120\n  become: yes\n  become_method: runas\n  become_user: SYSTEM\n\n- name: Configure Password Expiry Time\n  win_ad_object:\n    name: ms-Mcs-AdmPwdExpirationTime\n    attributes:\n      adminDescription: LAPS Password Expiration Time Attribute\n      lDAPDisplayName: ms-Mcs-AdmPwdExpirationTime\n      adminDisplayName: ms-Mcs-AdmPwdExpirationTime\n      attributeId: 1.2.840.113556.1.8000.2554.50051.45980.28112.18903.35903.6685103.1224907.2.2\n      attributeSyntax: '2.5.5.16'  # LargeInteger\n      omSyntax: 65  # LargeInteger\n      isSingleValued: True\n      systemOnly: False\n      isMemberOfPartialAttributeSet: False\n      searchFlags: 0\n      showInAdvancedViewOnly: False\n    context: schema\n    type: attribute\n    update_schema: True\n  register: password_expire_time\n  until: \"password_expire_time is not failed\"\n  retries: 3\n  delay: 120\n  become: yes\n  become_method: runas\n  become_user: SYSTEM\n\n- name: Add LAPS attributes to the Computer Attribute\n  win_ad_object:\n    name: Computer\n    may_contain:\n    - ms-Mcs-AdmPwd\n    - ms-Mcs-AdmPwdExpirationTime\n    context: schema\n    update_schema: True\n  register: add_laps_attribute\n  until: \"add_laps_attribute is not failed\"\n  retries: 3\n  delay: 120\n  become: yes\n  become_method: runas\n  become_user: SYSTEM\n\n- name: \"Apply DACL to OU Containers\"\n  win_ad_dacl:\n    path: \"{{laps_path}}\"\n    state: present\n    aces:\n    - rights:\n      - ReadProperty\n      - WriteProperty\n      inheritance_type: Descendents\n      inherited_object_type: Computer\n      object_type: ms-Mcs-AdmPwdExpirationTime\n      access: allow\n      account: S-1-5-10  # NT AUTHORITY\\SELF\n    - rights: WriteProperty\n      inheritance_type: Descendents\n      inherited_object_type: Computer\n      object_type: ms-Mcs-AdmPwd\n      access: allow\n      account: S-1-5-10\n\n- name: Create LAPS GPO\n  win_gpo:\n    name: '{{ opt_laps_gpo_name }}'\n    description: Setup by Ansible for LAPS\n    state: present\n  register: pri_laps_gpo\n\n- name: Add LAPS extension to GPO\n  win_ad_object:\n    name: '{{ pri_laps_gpo.path }}'\n    attributes:\n      # [Registry:Admin Tool][AdmPwd:Admin Tool]\n      gPCMachineExtensionNames: \"[{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{D02B1F72-3407-48AE-BA88-E8213C6761F1}]\\\n        [{D76B9641-3288-4F75-942D-087DE603E3EA}{D02B1F72-3407-48AE-BA88-E8213C6761F1}]\"\n\n- name: Configure Password Policy Settings on GPO\n  win_gpo_reg:\n    gpo: '{{ opt_laps_gpo_name }}'\n    name: '{{ item.name }}'\n    path: 'HKLM\\Software\\Policies\\Microsoft Services\\AdmPwd'\n    state: present\n    type: dword\n    value: '{{ item.value }}'\n  with_items:\n  - name: PasswordComplexity\n    value: 4\n  - name: PasswordLength\n    value: 14\n  - name: PasswordAgeDays\n    value: 30\n\n- name: Configure Expiration Protection on GPO\n  win_gpo_reg:\n    gpo: '{{ opt_laps_gpo_name }}'\n    name: PwdExpirationProtectionEnabled\n    path: 'HKLM\\Software\\Policies\\Microsoft Services\\AdmPwd'\n    state: present\n    type: dword\n    value: 1\n\n- name: Remove Configuration for Expiration Protection on GPO\n  win_gpo_reg:\n    gpo: '{{ opt_laps_gpo_name }}'\n    name: PwdExpirationProtectionEnabled\n    path: 'HKLM\\Software\\Policies\\Microsoft Services\\AdmPwd'\n    state: absent\n\n- name: Configure Custom Admin Username Policy on GPO\n  win_gpo_reg:\n    gpo: '{{ opt_laps_gpo_name }}'\n    name: AdminAccountName\n    path: 'HKLM\\Software\\Policies\\Microsoft Services\\AdmPwd'\n    state: present\n    type: string\n\n- name: Enable the GPO\n  win_gpo_reg:\n    gpo: '{{ opt_laps_gpo_name }}'\n    name: AdmPwdEnabled\n    path: 'HKLM\\Software\\Policies\\Microsoft Services\\AdmPwd'\n    state: present\n    type: dword\n    value: 1\n\n- name: Create Comment File for GPO\n  ansible.windows.win_copy:\n    src: ../files/comment.cmtx\n    dest: C:\\Windows\\SYSVOL\\domain\\Policies\\{{ '{' }}{{ pri_laps_gpo.id }}{{ '}' }}\\Machine\\comment.cmtx\n\n- name: Ensure GPO is Linked\n  win_gpo_link:\n    name: '{{ opt_laps_gpo_name }}'\n    target: '{{laps_path}}'\n    state: present\n    enforced: True\n    enabled: True"
  },
  {
    "path": "ansible/roles/laps/dc/tasks/main.yml",
    "content": "- name: laps dc install\n  import_tasks: install.yml\n  when: laps_path != false\n\n- name: move to laps ou\n  import_tasks: move_server_to_ou.yml\n  when: laps_path != false\n"
  },
  {
    "path": "ansible/roles/laps/dc/tasks/move_server_to_ou.yml",
    "content": "- name: Move server to Laps OU\n  win_shell: |\n    try {\n      Get-ADOrganizationalUnit -Identity \"{{laps_path}}\" > $null\n      $server=Get-AdComputer -Identity \"{{hostname}}\"\n      Move-ADObject -Identity $server.DistinguishedName -TargetPath \"{{laps_path}}\"\n      $true\n    } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {\n      $false\n    }\n  vars:\n    hostname: \"{{item.value.hostname}}\"\n  when: item.value.use_laps is defined and item.value.use_laps == true and item.value.domain == domain\n  with_dict: \"{{hosts_dict}}\""
  },
  {
    "path": "ansible/roles/laps/dc/vars/main.yml",
    "content": "---\n# converts opt_laps_password_policy_complexity to the value expected by GPO\npri_laps_password_policy_complexity:\n  uppercase: 1\n  uppercase,lowercase: 2\n  uppercase,lowercase,digits: 3\n  uppercase,lowercase,digits,symbols: 4\n\n# GPO variables\nopt_laps_gpo_name: ansible-laps\nopt_laps_password_policy_complexity: uppercase,lowercase,digits,symbols\nopt_laps_password_policy_length: 14\nopt_laps_password_policy_age: 30"
  },
  {
    "path": "ansible/roles/laps/permissions/tasks/main.yml",
    "content": "- name: Add user or group permission to read Laps\n  win_shell: |\n    Set-AdmPwdReadPasswordPermission -OrgUnit \"{{laps_path}}\" -AllowedPrincipals \"{{item}}\"\n  with_items: \"{{laps_readers}}\"\n  when: laps_readers is defined"
  },
  {
    "path": "ansible/roles/laps/server/tasks/install.yml",
    "content": "---\n- name: Install to Servers\n  ansible.windows.win_package:\n    arguments: \"ADDLOCAL=CSE\"\n    path: https://download.microsoft.com/download/C/7/A/C7AAD914-A8A6-4904-88A1-29E657445D03/LAPS.x64.msi\n    state: present\n    creates_path: \"%ProgramFiles%\\\\LAPS\"\n  register: pri_laps_install\n  until: pri_laps_install is success\n  retries: 3  # Try 3 times just in case it failed to download the URL\n  delay: 1\n\n- name: reboot after installing LAPS if required\n  ansible.windows.win_reboot:\n  when: pri_laps_install.reboot_required\n\n- name: Refresh GPO on the Clients\n  ansible.windows.win_command: gpupdate /force\n"
  },
  {
    "path": "ansible/roles/laps/server/tasks/main.yml",
    "content": "- name: laps server install\n  import_tasks: install.yml\n  when: laps_path != false and use_laps == true"
  },
  {
    "path": "ansible/roles/laps/verify/tasks/main.yml",
    "content": "- name: Retrieve LAPS Password on server\n  win_shell: |\n    $server=Get-AdComputer -Identity \"{{hostname}}\"\n    $obj = Get-ADObject -Identity $server.DistinguishedName -Properties ms-Mcs-AdmPwd\n    Write-Output \"{{hostname}}\" $obj.\"ms-Mcs-AdmPwd\"\n  register: powershell_password\n  vars:\n    hostname: \"{{item.value.hostname}}\"\n  when: item.value.use_laps is defined and item.value.use_laps == true and item.value.domain == domain\n  with_dict: \"{{hosts_dict}}\"\n\n- name: Show new laps password\n  debug: msg=\"{{item.stdout_lines}}\"\n  when: item.stdout_lines is defined\n  with_items: \"{{powershell_password.results}}\"\n"
  },
  {
    "path": "ansible/roles/linux/add_linux_to_domain/handlers/main.yml",
    "content": "- name: Restart SSH\n  service:\n    name: ssh\n    state: restarted\n\n- name: Restart SSSD\n  systemd:\n    name: sssd\n    state: restarted\n\n- name: Restart chrony\n  ansible.builtin.systemd:\n    name: chrony\n    state: restarted"
  },
  {
    "path": "ansible/roles/linux/add_linux_to_domain/tasks/main.yml",
    "content": "- name: update apt cache\n  apt: update_cache=yes\n\n- name: Install AD Packages\n  apt:\n    name:\n      - sssd-ad\n      - sssd-tools\n      - realmd\n      - adcli\n      - packagekit\n    state: present\n\n- name: Create KRB5 File\n  copy:\n    dest: \"/etc/krb5.conf\"\n    content: |\n      [libdefaults]\n      default_realm = {{ domain |upper}}\n      ticket_lifetime = 24h\n      renew_lifetime = 7d\n      dns_lookup_realm = true\n      dns_lookup_kdc = true\n      forward = true\n      forwardable = true\n\n      [realms]\n      {{ domain  |upper }} = {\n        admin_server = {{ dc_fqdn  |upper}}\n        kdc = {{ dc_fqdn  |upper}}\n      }\n\n      [domain_realm]\n      {{ domain }} =  {{ domain|upper }}\n      .{{ domain }} = {{ domain|upper }}\n\n- name: Install krb5 Packages\n  apt:\n    name:\n      - krb5-user\n      - sssd-krb5\n    state: present\n\n- name: Modify Hosts File to add current hostname\n  lineinfile:\n    dest: \"/etc/hosts\"\n    line: \"127.0.1.1       {{ hostname }}.{{ domain }}\"\n    state: present\n    backup: yes\n\n- name: Modify Hosts File to add domain dc \n  lineinfile:\n    dest: \"/etc/hosts\"\n    line: \"{{dc_ip}}       {{ dc_fqdn }}  {{ domain }}\"\n    state: present\n    backup: yes\n\n- name: Modify Hostname\n  shell:\n    \"sudo hostnamectl set-hostname {{ hostname }}.{{ domain }}\"\n\n- name: Kinit\n  shell:\n    \"echo {{ domain_password }} | sudo kinit {{ domain_username }}\"\n  register: result\n\n- name: Print Kinit Result\n  debug: var=result.stdout_lines\n\n- name: Check if domain joined\n  shell:\n    \"realm list\"\n  register: domain_joined\n\n- name: Print realm list Result\n  debug: var=domain_joined.stdout_lines\n\n- name: Join Realm\n  shell:\n    \"echo {{ domain_password }} | sudo realm join -v -U {{ domain_username }} {{ domain }}\"\n  when: not domain in domain_joined.stdout_lines\n  register: result\n\n- name: Print Realm Result\n  debug: var=result.stdout_lines\n  when: not domain in domain_joined.stdout_lines\n\n- name: Activate Homedir Creation\n  shell:\n    \"sudo pam-auth-update --enable mkhomedir\"\n\n- name: Modify SSDCONF Line 1 Ubuntu\n  replace:\n    path: /etc/sssd/sssd.conf\n    regexp: 'use_fully_qualified_names = True'\n    replace: 'use_fully_qualified_names = False'\n\n- name: Modify SSDCONF Line 2 Ubuntu\n  replace:\n    path: /etc/sssd/sssd.conf\n    regexp: 'fallback_homedir = /home/%u@%d'\n    replace: 'fallback_homedir = /home/%u'\n\n- name: Add {{ item }} to Sudoers Ubuntu\n  lineinfile:\n    dest: \"/etc/sudoers\"\n    line: \"%{{ item }}   ALL=(ALL) NOPASSWD:ALL\"\n    state: present\n    validate: /usr/sbin/visudo -cf %s\n    backup: yes\n  loop: \"{{sudoers_group}}\"\n\n- name: Allow {{ item }} Login Ubuntu\n  shell:\n    \"realm permit -g {{ item }}@{{ domain }}\"\n  loop: \"{{ssh_group}}\"\n\n- name: Enable GSSAPI Authentication in SSHD\n  lineinfile:\n    path: /etc/ssh/sshd_config\n    regexp: '^#?GSSAPIAuthentication'\n    line: 'GSSAPIAuthentication yes'\n    state: present\n    backup: yes\n\n- name: Enable GSSAPI Cleanup Credentials\n  lineinfile:\n    path: /etc/ssh/sshd_config\n    regexp: '^#?GSSAPICleanupCredentials'\n    line: 'GSSAPICleanupCredentials yes'\n    state: present\n    backup: yes\n\n- name: Disable GSSAPIStrictAcceptorCheck\n  lineinfile:\n    path: /etc/ssh/sshd_config\n    regexp: '^#?GSSAPIStrictAcceptorCheck'\n    line: 'GSSAPIStrictAcceptorCheck no'\n    state: present\n    backup: yes\n\n- name: Ensure PAM is enabled in SSHD\n  lineinfile:\n    path: /etc/ssh/sshd_config\n    regexp: '^#?UsePAM'\n    line: 'UsePAM yes'\n    state: present\n    backup: yes\n\n- name: Install PAM Kerberos module\n  apt:\n    name: libpam-krb5\n    state: present\n  notify: Restart SSH\n\n- name: Add ssh\n  shell:\n    \"sudo realm join --client-software=sssd {{ domain }}\"\n  ignore_errors: yes\n\n- name: Define domain DNS in resolved.conf\n  lineinfile:\n    path: /etc/systemd/resolved.conf\n    regexp: '^#?DNS='\n    line: \"DNS={{dc_ip}}\"\n\n- name: restart systemd-resolved\n  systemd:\n    name: systemd-resolved\n    state: restarted\n\n- name: Fix symlink resolv.conf\n  file:\n    src: /run/systemd/resolve/resolv.conf\n    dest: /etc/resolv.conf\n    state: link\n    force: yes\n\n- name: Install ntpdate\n  ansible.builtin.apt:\n    name: ntpdate\n    state: present\n    update_cache: true\n\n- name: Force immediate time sync with DC\n  ansible.builtin.command:\n    cmd: \"ntpdate -u {{ dc_ip }}\"\n\n- name: Install chrony\n  ansible.builtin.apt:\n    name: chrony\n    state: present\n    update_cache: yes\n\n- name: Configure DC as NTP server\n  ansible.builtin.lineinfile:\n    path: /etc/chrony/chrony.conf\n    regexp: '^server {{ dc_ip }}'\n    line: \"server {{ dc_ip }} iburst\"\n    state: present\n    insertafter: EOF\n  notify:\n    - Restart chrony\n\n- name: Remove default Ubuntu NTP pools\n  ansible.builtin.replace:\n    path: /etc/chrony/chrony.conf\n    regexp: '^pool .*$'\n    replace: ''\n  notify:\n    - Restart chrony\n\n- name: Set makestep to 1 -1\n  ansible.builtin.lineinfile:\n    path: /etc/chrony/chrony.conf\n    regexp: '^makestep'\n    line: \"makestep 1 -1\"\n    state: present\n  notify:\n    - Restart chrony\n\n- name: Ensure chrony is started and enabled\n  ansible.builtin.systemd:\n    name: chrony\n    state: started\n    enabled: yes\n\n- name: Set RTC in local timezone and adjust system clock\n  ansible.builtin.command:\n    cmd: timedatectl set-local-rtc 1 --adjust-system-clock\n\n- name: Force immediate time sync\n  ansible.builtin.command:\n    cmd: chronyc -a makestep\n\n- name: Remove faulty ad_server line to enable auto-discovery\n  lineinfile:\n    path: /etc/sssd/sssd.conf\n    regexp: '^ad_server\\s*='\n    state: absent\n    backup: yes\n  notify:\n    - Restart SSSD"
  },
  {
    "path": "ansible/roles/linux/apache/files/000-default.conf",
    "content": "<VirtualHost *:80>\n    ServerName server.local\n    ServerAdmin admin@server.local\n    DocumentRoot /var/www/html\n\n    <Directory /var/www/html>\n            Options FollowSymLinks\n            AllowOverride None\n            Require all granted\n    </Directory>\n</VirtualHost>"
  },
  {
    "path": "ansible/roles/linux/apache/handlers/main.yml",
    "content": "---\n- name: restart apache\n  service:\n    name: apache2\n    state: restarted"
  },
  {
    "path": "ansible/roles/linux/apache/tasks/main.yml",
    "content": "- name: Install Apache\n  apt: \n    name: apache2\n    state: latest\n\n- name: Change Apache default vhost\n  copy:\n    src: 000-default.conf\n    dest: /etc/apache2/sites-available/000-default.conf\n    owner: \"root\"\n    group: \"root\"\n    force: yes\n    mode: 0644\n\n- name: Start Apache service and enable\n  service: \n    name: apache2\n    state: started\n    enabled: true\n\n- name: Enable Apache mods\n  command: a2enmod {{ item }}\n  with_items:\n    - headers\n    - ssl\n    - rewrite\n  notify: restart apache"
  },
  {
    "path": "ansible/roles/linux/common/files/common.sh",
    "content": "#!/bin/sh\n# ANSIBLE MANAGED: DO NOT EDIT MANUALLY\n\n# file copied in /etc/profile.d/ by conf-utils.sh\n# aliases for all users (included root)\n\nalias ls='ls --color=auto'\nalias grep='grep --color=auto'\nalias fgrep='fgrep --color=auto'\nalias egrep='egrep --color=auto'\nalias l='ls '\nalias ll='ls -alF'\nalias la='ls -A'\n\nPS1='\\[\\033[01;32m\\]\\u@\\h\\[\\033[00m\\]:\\[\\033[36m\\]\\w\\[\\033[00m\\]\\$ '"
  },
  {
    "path": "ansible/roles/linux/common/tasks/main.yml",
    "content": "######################################\n# Update and upgrade\n######################################\n- name: update and upgrade apt\n  apt:\n    upgrade: yes\n    update_cache: yes\n    cache_valid_time: 86400 #One day\n\n######################################\n# Generic tools\n######################################\n- name: Install usefull system tools\n  apt: name={{ item }} state=present\n  with_items:\n    - vim\n    - htop\n    - git\n    - openssl\n    - tmux\n    - curl\n    - tar\n    - nano\n    - rsync\n\n# ######################################\n# # Time management\n# ######################################\n# - name: Set local timezone\n#   copy: content={{ timezone }}\n#         dest=/etc/timezone\n# \n# - name: Reconfigure tzdata\n#   command: dpkg-reconfigure -f noninteractive tzdata\n# \n# - name: Install NTP (and update apt cache for the first install)\n#   apt: name=ntp state=present\n#         update_cache=yes\n# \n# - name: Start the ntp service\n#   service: name=ntp state=started enabled=true\n\n######################################\n# Copy system files\n######################################\n- name: add profile common\n  copy:\n    src: common.sh\n    dest: /etc/profile.d/common.sh\n    owner: \"root\"\n    group: \"root\"\n    mode: 0755\n"
  },
  {
    "path": "ansible/roles/linux/disable_user/tasks/main.yml",
    "content": "- name: \"Disable the user {{ username }}\"\n  ansible.builtin.user:\n    name: \"{{ username }}\"\n    password_lock: true"
  },
  {
    "path": "ansible/roles/linux/enable_user/tasks/main.yml",
    "content": "- name: \"Disable the user {{ username }}\"\n  ansible.builtin.user:\n    name: \"{{ username }}\"\n    password_lock: false"
  },
  {
    "path": "ansible/roles/linux/glpi/defaults/main.yml",
    "content": "---\nglpi_install_path: \"/var/www/html\"\nglpi_version: \"10.0.17\"\nglpi_download_url: \"https://github.com/glpi-project/glpi/releases/download/{{glpi_version}}/glpi-{{glpi_version}}.tgz\"\nglpi_db_host: \"localhost\"\nglpi_db_port: \"3306\"\nglpi_db_name: \"glpi\"\nglpi_db_user: \"glpi\"\nglpi_db_password: \"glpi\"\nglpi_force_reinstall: false\nglpi_ldap:\n  name: \"ldap\"\n  host: \"192.168.10.10\"\n  basedn: \"DC=balerion,DC=dracarys,DC=lab\"\n  rootdn: \"sunfyre@balerion.dracarys.lab\"\n  port: 389\n  glpi_user_password: \"XXXX\""
  },
  {
    "path": "ansible/roles/linux/glpi/files/glpi_config.php",
    "content": "<?php\nif ($argc !== 7) {\n    echo \"Usage: php {$argv[0]} db_host db_name db_user db_password config value\\n\";\n    exit(1);\n}\n\n$db_host     = $argv[1];\n$db_name     = $argv[2];\n$db_user     = $argv[3];\n$db_password = $argv[4];\n$config      = $argv[5];\n$value       = $argv[6];\n\n$mysqli = new mysqli($db_host, $db_user, $db_password, $db_name);\nif ($mysqli->connect_error) {\n    die(\"Connection failed: \" . $mysqli->connect_error . \"\\n\");\n}\n$mysqli->set_charset('utf8mb4');\n\n// Génère le datetime MySQL correct\n$datetime = date(\"Y-m-d H:i:s\");\n\n// Mise à jour de la configuration\n$sql = \"\n    UPDATE glpi_configs\n    SET value = ?\n    WHERE name = ?\n\";\n\n$stmt = $mysqli->prepare($sql);\n$stmt->bind_param(\"ss\", $value, $config);\n\nif ($stmt->execute()) {\n    if ($stmt->affected_rows > 0) {\n        echo \"Configuration updated successfully for config '{$config}'\\n\";\n    } else {\n        echo \"No configuration udpated.\\n\";\n    }\n} else {\n    echo \"SQL error: \" . $stmt->error . \"\\n\";\n}\n\n$stmt->close();\n$mysqli->close();\n"
  },
  {
    "path": "ansible/roles/linux/glpi/files/glpi_insert_mail.php",
    "content": "<?php\n// usage: php glpi_password.php db_host db_name db_user db_password\n\nif ($argc !== 7) {\n    echo \"Usage: php {$argv[0]} db_host db_name db_user db_password user email\\n\";\n    exit(1);\n}\n\n$db_host     = $argv[1];\n$db_name     = $argv[2];\n$db_user     = $argv[3];\n$db_password = $argv[4];\n$user        = $argv[5];\n$email       = $argv[6];\n\n$mysqli = new mysqli($db_host, $db_user, $db_password, $db_name);\nif ($mysqli->connect_error) {\n    die(\"Connection failed: \" . $mysqli->connect_error . \"\\n\");\n}\n$mysqli->set_charset('utf8mb4');\n\n// Mise à jour du mot de passe + timestamp DATETIME\n$sql = \"\n    INSERT INTO glpi_useremails (users_id, email, is_default)\n    VALUES (\n        (SELECT id FROM glpi_users WHERE name = ?),\n        ?,\n        1\n    ) \n    ON DUPLICATE KEY UPDATE email = VALUES(email);\n\";\n\n$stmt = $mysqli->prepare($sql);\n$stmt->bind_param(\"ss\", $user, $email);\n\nif ($stmt->execute()) {\n    if ($stmt->affected_rows > 0) {\n        echo \"Email setup successfully'\\n\";\n    } else {\n        echo \"No user updated.\\n\";\n    }\n} else {\n    echo \"SQL error: \" . $stmt->error . \"\\n\";\n}\n\n$stmt->close();\n$mysqli->close();\n"
  },
  {
    "path": "ansible/roles/linux/glpi/files/glpi_ldap.php",
    "content": "<?php\n\n// Usage : php glpi_ldap_add.php <db_host> <db_name> <db_user> <db_pass> <ldap_name> <ldap_host> <ldap_basedn> <ldap_rootdn> <ldap_port> <ldap_filter> <ldap_password>\n\nif ($argc !== 12) {\n    echo \"Usage: php {$argv[0]} <db_host> <db_name> <db_user> <db_pass> <ldap_name> <ldap_host> <ldap_basedn> <ldap_rootdn> <ldap_port> <ldap_filter> <ldap_password>\\n\";\n    exit(1);\n}\n\n// --- Assignation des arguments ---\n$db_host        = $argv[1];\n$db_name        = $argv[2];\n$db_user        = $argv[3];\n$db_password    = $argv[4];\n\n$ldap_name      = $argv[5];\n$ldap_host      = $argv[6];\n$ldap_basedn    = $argv[7];\n$ldap_rootdn    = $argv[8];\n$ldap_port      = (int)$argv[9];\n$ldap_filter    = $argv[10];\n$ldap_password  = $argv[11];\n\n// Champs LDAP GLPI\n$ldap_login     = \"samaccountname\";\n$ldap_email     = \"mail\";\n$ldap_realname  = \"sn\";\n$ldap_firstname = \"givenname\";\n$ldap_phone     = \"telephonenumber\";\n$ldap_is_default= 1;\n$ldap_is_active = 1;\n\n// --- Fonction d'encryptage GLPI ---\nfunction encrypt_string(string $string, string $key): string\n{\n    $nonce = random_bytes(SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES);\n\n    $encrypted = sodium_crypto_aead_xchacha20poly1305_ietf_encrypt(\n        $string,\n        $nonce,\n        $nonce,\n        $key\n    );\n\n    return base64_encode($nonce . $encrypted);\n}\n\n// --- Lecture de la clé GLPI ---\n$key = file_get_contents(\"/var/www/html/glpi/config/glpicrypt.key\");\nif (!$key) {\n    die(\"Cannot read GLPI encryption key\\n\");\n}\n\n$encrypted_pass = encrypt_string($ldap_password, $key);\n\n// --- Connexion DB ---\n$conn = new mysqli($db_host, $db_user, $db_password, $db_name);\nif ($conn->connect_error) {\n    die(\"Database connection error: \" . $conn->connect_error . \"\\n\");\n}\n\n// --- Vérifier si l'entrée LDAP existe déjà ---\n$check = $conn->prepare(\"SELECT id FROM glpi_authldaps WHERE name = ?\");\n$check->bind_param(\"s\", $ldap_name);\n$check->execute();\n$check->store_result();\n\nif ($check->num_rows > 0) {\n    // --- UPDATE ---\n    $check->bind_result($existing_id);\n    $check->fetch();\n    $check->close();\n\n    $sql = \"\n        UPDATE glpi_authldaps\n        SET host=?, basedn=?, rootdn=?, port=?, `condition`=?, login_field=?, email1_field=?, \n            realname_field=?, firstname_field=?, phone_field=?, is_default=?, is_active=?, rootdn_passwd=?\n        WHERE id=?\n    \";\n\n    $stmt = $conn->prepare($sql);\n    $stmt->bind_param(\n        \"sssissssssissi\",\n        $ldap_host,\n        $ldap_basedn,\n        $ldap_rootdn,\n        $ldap_port,\n        $ldap_filter,\n        $ldap_login,\n        $ldap_email,\n        $ldap_realname,\n        $ldap_firstname,\n        $ldap_phone,\n        $ldap_is_default,\n        $ldap_is_active,\n        $encrypted_pass,\n        $existing_id\n    );\n\n    if ($stmt->execute()) {\n        echo \"LDAP configuration UPDATED successfully (id=$existing_id).\\n\";\n    } else {\n        echo \"SQL UPDATE error: \" . $stmt->error . \"\\n\";\n    }\n\n    $stmt->close();\n\n} else {\n    // --- INSERT ---\n    $check->close();\n\n    $sql = \"\n        INSERT INTO glpi_authldaps\n            (name, host, basedn, rootdn, port, `condition`, login_field, email1_field,\n             realname_field, firstname_field, phone_field, is_default, is_active, rootdn_passwd)\n        VALUES (\n            ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?\n        )\n    \";\n\n    $stmt = $conn->prepare($sql);\n\n    $stmt->bind_param(\n        \"ssssissssssiss\",\n        $ldap_name,\n        $ldap_host,\n        $ldap_basedn,\n        $ldap_rootdn,\n        $ldap_port,\n        $ldap_filter,\n        $ldap_login,\n        $ldap_email,\n        $ldap_realname,\n        $ldap_firstname,\n        $ldap_phone,\n        $ldap_is_default,\n        $ldap_is_active,\n        $encrypted_pass\n    );\n\n    if ($stmt->execute()) {\n        echo \"LDAP configuration INSERTED successfully.\\n\";\n    } else {\n        echo \"SQL INSERT error: \" . $stmt->error . \"\\n\";\n    }\n\n    $stmt->close();\n}\n\n$conn->close();\n"
  },
  {
    "path": "ansible/roles/linux/glpi/files/glpi_password.php",
    "content": "<?php\n// usage: php glpi_password.php db_host db_name db_user db_password glpi_user new_password\n\nif ($argc !== 7) {\n    echo \"Usage: php {$argv[0]} db_host db_name db_user db_password glpi_user new_password\\n\";\n    exit(1);\n}\n\n$db_host     = $argv[1];\n$db_name     = $argv[2];\n$db_user     = $argv[3];\n$db_password = $argv[4];\n$glpi_user   = $argv[5];\n$new_pass    = $argv[6];\n\n// Hash bcrypt compatible GLPI\n$hash = password_hash($new_pass, PASSWORD_DEFAULT);\n\n$mysqli = new mysqli($db_host, $db_user, $db_password, $db_name);\nif ($mysqli->connect_error) {\n    die(\"Connection failed: \" . $mysqli->connect_error . \"\\n\");\n}\n$mysqli->set_charset('utf8mb4');\n\n// Génère le datetime MySQL correct\n$datetime = date(\"Y-m-d H:i:s\");\n\n// Mise à jour du mot de passe + timestamp DATETIME\n$sql = \"\n    UPDATE glpi_users\n    SET password = ?, password_last_update = ?\n    WHERE name = ?\n\";\n\n$stmt = $mysqli->prepare($sql);\n$stmt->bind_param(\"sss\", $hash, $datetime, $glpi_user);\n\nif ($stmt->execute()) {\n    if ($stmt->affected_rows > 0) {\n        echo \"Password updated successfully for user '{$glpi_user}'\\n\";\n    } else {\n        echo \"No user updated. Check username or authtype.\\n\";\n    }\n} else {\n    echo \"SQL error: \" . $stmt->error . \"\\n\";\n}\n\n$stmt->close();\n$mysqli->close();\n"
  },
  {
    "path": "ansible/roles/linux/glpi/tasks/main.yml",
    "content": "# force reinstall if needed\n- name: Check if already installed\n  file:\n    path: \"{{ glpi_install_path }}/glpi\"\n    state: absent\n  when: glpi_force_reinstall\n\n# verify if installation is already done\n- name: Check if already installed\n  stat:\n    path: \"{{ glpi_install_path }}/glpi\"\n  register: glpi_is_installed\n\n# due to a bug with old ansible and unarchive\n- name: Download GLPI with curl\n  command: >\n    curl -L -k \"{{ glpi_download_url }}\" -o /tmp/glpi.tgz\n  args:\n    creates: /tmp/glpi.tgz\n  when: not glpi_is_installed.stat.exists\n\n- name: Extract GLPI\n  unarchive:\n    src: \"/tmp/glpi.tgz\"\n    dest: \"{{ glpi_install_path }}\"\n    owner: \"www-data\"\n    group: \"www-data\"\n    remote_src: true\n  when: not glpi_is_installed.stat.exists\n\n- name: Set permisions to glpi directory\n  file:\n    path: \"{{ glpi_install_path }}/glpi/files\"\n    recurse: true\n    owner: \"www-data\"\n    group: \"www-data\"\n  when: not glpi_is_installed.stat.exists\n\n- name: Set permissions to config directory\n  file:\n    path: \"{{ glpi_install_path }}/glpi/config\"\n    recurse: true\n    owner: \"www-data\"\n    group: \"www-data\"\n  when: not glpi_is_installed.stat.exists\n\n- name: Set permissions to all glpi directory\n  file:\n    path: \"{{ glpi_install_path }}/\"\n    recurse: true\n    owner: \"www-data\"\n    group: \"www-data\"\n  when: not glpi_is_installed.stat.exists\n\n# Launch install\n- name: Automatic installation\n  command: \"php bin/console -n db:install -H {{ glpi_db_host }} -P {{ glpi_db_port }} -d {{ glpi_db_name }} -u {{ glpi_db_user }} -p {{ glpi_db_password }}\"\n  args:\n    chdir: \"{{ glpi_install_path }}/glpi\"\n  when: not glpi_is_installed.stat.exists\n\n- name: Remove install.php\n  file:\n    path: \"{{ glpi_install_path }}/glpi/install/install.php\"\n    state: absent\n  when: not glpi_is_installed.stat.exists\n\n- name: Check if certificate is already present\n  stat:\n    path: /usr/local/share/ca-certificates/dc-ca.crt\n  register: ca_cert\n\n- name: Retrieve the certificate from the DC via openssl\n  shell: |\n    echo -n | openssl s_client -connect {{ glpi_ldap.host }}:636 -showcerts 2>/dev/null \\\n    | awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/ {print $0}' > /usr/local/share/ca-certificates/dc-ca.crt\n  when: not ca_cert.stat.exists\n\n- name: Update CA certificates store only if not already installed\n  command: update-ca-certificates\n  register: update_ca\n  changed_when: \"'1 added' in update_ca.stdout or '0 added' not in update_ca.stdout\"\n  when: not ca_cert.stat.exists\n\n- name: Reboot if CA certificates were updated\n  ansible.builtin.reboot:\n    msg: \"Rebooting after new CA certificate installation\"\n    pre_reboot_delay: 5\n    post_reboot_delay: 30\n  when: update_ca.changed\n\n- name: Configure LDAP for GLPI\n  ansible.builtin.script: >\n    files/glpi_ldap.php\n    {{ glpi_db_host }}\n    {{ glpi_db_name }}\n    {{ glpi_db_user }}\n    {{ glpi_db_password }}\n    {{ glpi_ldap.name }}\n    ldaps://{{ glpi_ldap.host }}\n    {{ glpi_ldap.basedn }}\n    {{ glpi_ldap.rootdn }}\n    {{ glpi_ldap.port | string }}\n    \"(&(objectClass=user)(objectCategory=person))\"\n    {{ glpi_ldap.glpi_user_password }}\n  args:\n    executable: php\n\n- name: Change GLPI default users passwords\n  ansible.builtin.script: >\n    files/glpi_password.php\n    {{ glpi_db_host }}\n    {{ glpi_db_name }}\n    {{ glpi_db_user }}\n    {{ glpi_db_password }}\n    {{ item }}\n    {{ glpi_local_users_pass }}\n  args:\n    executable: php\n  loop:\n    - glpi\n    - tech\n    - normal\n    - post-only\n\n\n- name: Enable GLPI inventory\n  ansible.builtin.script: >\n    files/glpi_config.php\n    {{ glpi_db_host }}\n    {{ glpi_db_name }}\n    {{ glpi_db_user }}\n    {{ glpi_db_password }}\n    enabled_inventory\n    1\n  args:\n    executable: php\n\n\n- name: Enable GLPI notifications and forgot password\n  ansible.builtin.script: >\n    files/glpi_config.php\n    {{ glpi_db_host }}\n    {{ glpi_db_name }}\n    {{ glpi_db_user }}\n    {{ glpi_db_password }}\n    {{ item }}\n    1\n  args:\n    executable: php\n  loop:\n    - use_notifications\n    - notifications_mailing\n\n- name: Add GLPI email for default user\n  ansible.builtin.script: >\n    files/glpi_insert_mail.php\n    {{ glpi_db_host }}\n    {{ glpi_db_name }}\n    {{ glpi_db_user }}\n    {{ glpi_db_password }}\n    {{ item }}\n    \"noreply@dracarys.lab\"\n  args:\n    executable: php\n  loop:\n    - glpi\n\n- name: Set write permissions to glpi directory (for logs and other stuff made has root during provisioning)\n  file:\n    path: \"{{ glpi_install_path }}\"\n    recurse: true\n    owner: \"www-data\"\n    group: \"www-data\""
  },
  {
    "path": "ansible/roles/linux/guacamole/README.md",
    "content": "modified version of https://github.com/mrlesmithjr/ansible-guacamole/tree/master (MIT license)"
  },
  {
    "path": "ansible/roles/linux/guacamole/defaults/main.yml",
    "content": "GUACAMOLE_VERSION: 1.6.0\nGUACAMOLE_TMP_DIR: /tmp\nGUACAMOLE_INSTALL_DIR: /opt/guacamole\nguacamole_db: guacamole\nguacamole_db_username: guacamole\nguacamole_db_password: guacamole"
  },
  {
    "path": "ansible/roles/linux/guacamole/handlers/main.yml",
    "content": "- name: restart tomcat9\n  service: \n    name: tomcat9\n    state: restarted\n\n- name: kill guacd\n  ansible.builtin.command: pkill guacd\n\n- name: restart guacd\n  service: \n    name: guacd\n    state: restarted"
  },
  {
    "path": "ansible/roles/linux/guacamole/tasks/client.yml",
    "content": "---\n- name: Creates guacamole directory\n  file:\n    path: /etc/guacamole\n    state: directory\n\n- name: check if guacamole client downloaded\n  ansible.builtin.stat:\n    path: \"{{ '/etc/guacamole/guacamole-' + GUACAMOLE_VERSION + '.war' }}\"\n  register: guacamole_client_downloaded\n\n- name: downloading Guacamole Client Package\n  ansible.builtin.get_url:\n    url: \"https://apache.org/dyn/closer.lua/guacamole/{{GUACAMOLE_VERSION}}/binary/guacamole-{{GUACAMOLE_VERSION}}.war?action=download\"\n    dest: \"{{ '/etc/guacamole/guacamole-' + GUACAMOLE_VERSION + '.war' }}\"\n  register: client_war\n  when: not guacamole_client_downloaded.stat.exists\n\n- name: check if guacamole client deployed\n  ansible.builtin.stat:\n    path: \"{{ '/var/lib/tomcat9/webapps/guacamole##' + GUACAMOLE_VERSION + '.war' }}\"\n  register: guacamole_client_deployed\n\n- name: setting Permissions On Tomcat Symlink For {{ 'guacamole-' + guacamole_version + '.war' }}\n  ansible.builtin.file:\n    path: \"{{ '/etc/guacamole/guacamole-' + GUACAMOLE_VERSION + '.war' }}\"\n    owner: \"tomcat\"\n    group: \"tomcat\"\n\n- name: creating Tomcat Symlink For {{ 'guacamole-' + GUACAMOLE_VERSION + '.war' }}\n  ansible.builtin.file:\n    src: \"{{ '/etc/guacamole/guacamole-' + GUACAMOLE_VERSION + '.war' }}\"\n    dest: \"{{ '/var/lib/tomcat9/webapps/guacamole##' + GUACAMOLE_VERSION + '.war' }}\"\n    state: link\n  notify:\n    - restart tomcat9\n    - kill guacd\n    - restart guacd\n  when: not guacamole_client_deployed.stat.exists\n\n"
  },
  {
    "path": "ansible/roles/linux/guacamole/tasks/config.yml",
    "content": "- name: Add guacamole properties file\n  template:\n    src: guacamole.properties.j2\n    dest: /etc/guacamole/guacamole.properties\n    owner: \"root\"\n    group: \"root\"\n    force: yes\n    mode: 0644\n\n- name: Add guadc conf file\n  template:\n    src: guacd.conf.j2\n    dest: /etc/guacamole/guacd.conf\n    owner: \"root\"\n    group: \"root\"\n    force: yes\n    mode: 0644\n  notify:\n    - restart tomcat9\n    - kill guacd\n    - restart guacd\n\n- name: enable guacd\n  ansible.builtin.service:\n    name: guacd\n    enabled: true\n    state: started"
  },
  {
    "path": "ansible/roles/linux/guacamole/tasks/jdbc.yml",
    "content": "- name: Install mysql java connector\n  ansible.builtin.apt:\n    name: \n      - libmariadb-java\n    state: present\n\n- name: downloading Auth JDBC Library and unarchive\n  ansible.builtin.unarchive:\n    src: \"https://apache.org/dyn/closer.lua/guacamole/{{GUACAMOLE_VERSION}}/binary/guacamole-auth-jdbc-{{GUACAMOLE_VERSION}}.tar.gz?action=download\"\n    dest: \"{{ GUACAMOLE_INSTALL_DIR }}\"\n    remote_src: true\n\n- name: Creates guacamole extensions directory\n  file:\n    path: /etc/guacamole/extensions/\n    state: directory\n\n- name: copying Auth JDBC Connector\n  ansible.builtin.copy:\n    src: \"{{GUACAMOLE_INSTALL_DIR}}/guacamole-auth-jdbc-{{GUACAMOLE_VERSION}}/mysql/guacamole-auth-jdbc-mysql-{{GUACAMOLE_VERSION}}.jar\"\n    dest: /etc/guacamole/extensions/\n    owner: \"tomcat\"\n    group: \"tomcat\"\n    remote_src: true\n\n- name: Creates guacamole lib directory\n  file:\n    path: /etc/guacamole/lib/\n    state: directory\n\n- name: copy connector\n  ansible.builtin.copy:\n    src: /usr/share/java/mariadb-java-client.jar\n    dest: /etc/guacamole/lib/mariadb-java-client.jar\n    owner: \"tomcat\"\n    group: \"tomcat\"\n    remote_src: true\n\n- name: creating Guacamole DB\n  community.mysql.mysql_db:\n    name: \"{{ guacamole_db }}\"\n    login_host: \"localhost\"\n    login_port: \"3306\"\n    login_user: \"root\"\n    login_password: \"{{ mysql_root_password }}\"\n    state: present\n\n- name: creating Guacamole DB User\n  community.mysql.mysql_user:\n    name: \"{{ guacamole_db_username }}\"\n    password: \"{{ guacamole_db_password }}\"\n    login_host: \"localhost\"\n    login_port: \"3306\"\n    login_user: \"root\"\n    login_password: \"{{ mysql_root_password }}\"\n    column_case_sensitive: true\n    priv: \"{{ guacamole_db + '.*:GRANT,SELECT,INSERT,UPDATE,DELETE' }}\"\n    state: present\n\n- name: checking If DB Has Been Populated\n  ansible.builtin.stat:\n    path: /etc/guacamole/.db_populated\n  register: guacamole_db_populated_check\n\n- name: popluating DB\n  community.mysql.mysql_db:\n    name: \"{{ guacamole_db_username }}\"\n    login_host: \"localhost\"\n    login_port: \"3306\"\n    login_user: \"root\"\n    login_password: \"{{ mysql_root_password }}\"\n    state: import\n    target: \"{{GUACAMOLE_INSTALL_DIR}}/guacamole-auth-jdbc-{{GUACAMOLE_VERSION}}/mysql/schema/{{item }}\"\n  become: true\n  register: guacamole_db_populated\n  notify:\n    - restart tomcat9\n    - kill guacd\n    - restart guacd\n  with_items:\n    - 001-create-schema.sql\n    - 002-create-admin-user.sql\n  when: not guacamole_db_populated_check.stat.exists\n\n- name: mark DB As Populated\n  ansible.builtin.file:\n    path: /etc/guacamole/.db_populated\n    state: touch\n  when: guacamole_db_populated.changed\n\n- name: config | Creating Tomcat symlink For guacamole.properties\n  ansible.builtin.file:\n    src: /etc/guacamole\n    dest: /usr/share/tomcat9/.guacamole\n    state: link\n    owner: tomcat\n    group: tomcat\n  notify:\n    - restart tomcat9\n    - kill guacd\n    - restart guacd\n\n- name: Update index.hmtl of ROOT in tomcat to redirect to guacamole\n  ansible.builtin.copy:\n    content: \"<meta http-equiv='Refresh' content=\\\"0; url='/guacamole'\\\"/>\"\n    dest: \"/var/lib/tomcat9/webapps/ROOT/index.html\"\n"
  },
  {
    "path": "ansible/roles/linux/guacamole/tasks/main.yml",
    "content": "- name: server\n  import_tasks: server.yml\n\n- name: client\n  import_tasks: client.yml\n\n- name: config\n  import_tasks: config.yml\n\n- name: jdbc\n  import_tasks: jdbc.yml\n\n- name: user\n  import_tasks: user.yml"
  },
  {
    "path": "ansible/roles/linux/guacamole/tasks/server.yml",
    "content": "- name: Install Guacamole dependencies\n  ansible.builtin.apt:\n    name: \n      - freerdp2-x11\n      - freerdp2-dev\n      - build-essential\n      - libavcodec-dev\n      - libavutil-dev\n      - libcairo2-dev\n      - libjpeg-turbo8-dev\n      - libossp-uuid-dev\n      - libpango1.0-dev\n      - libpng-dev\n      - libpulse-dev\n      - libssh2-1-dev\n      - libssl-dev\n      - libswscale-dev\n      - libtelnet-dev\n      - libvncserver-dev\n      - libvorbis-dev\n      - libwebp-dev\n      - libwebsockets-dev\n      - libavformat-dev\n      - autoconf\n    state: present\n\n- name: check if guacamole server installed\n  ansible.builtin.stat:\n    path: /usr/local/bin/guaclog\n  register: guacamole_server_installed\n\n- name: checking if Guacamole folder exist\n  ansible.builtin.stat:\n    path: \"{{ GUACAMOLE_INSTALL_DIR + '/guacamole-server-' + GUACAMOLE_VERSION }}\"\n  register: guacamole_server_extracted\n\n- name: Creates guacamole directory\n  file:\n    path: \"{{GUACAMOLE_INSTALL_DIR}}\"\n    state: directory\n  when: not guacamole_server_extracted.stat.exists\n\n- name: Download guacamole Server Package\n  ansible.builtin.get_url:\n    url: \"https://apache.org/dyn/closer.lua/guacamole/{{GUACAMOLE_VERSION}}/source/guacamole-server-{{GUACAMOLE_VERSION}}.tar.gz?action=download\"\n    dest: \"{{GUACAMOLE_TMP_DIR}}\"\n  when: not guacamole_server_extracted.stat.exists\n\n- name: Extract guacamole tar.gz\n  ansible.builtin.unarchive:\n    src: \"{{ GUACAMOLE_TMP_DIR + '/guacamole-server-' + GUACAMOLE_VERSION + '.tar.gz' }}\"\n    dest: \"{{ GUACAMOLE_INSTALL_DIR }}\"\n    remote_src: true\n  when: not guacamole_server_extracted.stat.exists\n\n- name: Configuring guacamole\n  ansible.builtin.command: \"./configure --with-init-dir=/etc/init.d\"\n  args:\n    chdir: \"{{ GUACAMOLE_INSTALL_DIR + '/guacamole-server-' + GUACAMOLE_VERSION }}\"\n  register: guacamole_config\n  when: not guacamole_server_installed.stat.exists\n\n- name: Make guacamole\n  ansible.builtin.command: \"make\"\n  args:\n    chdir: \"{{ GUACAMOLE_INSTALL_DIR + '/guacamole-server-' + GUACAMOLE_VERSION }}\"\n  register: guacamole_make\n  when: guacamole_config['changed']\n\n- name: Make Install guacamole\n  ansible.builtin.command: \"make install\"\n  args:\n    chdir: \"{{ GUACAMOLE_INSTALL_DIR + '/guacamole-server-' + GUACAMOLE_VERSION }}\"\n  register: guacamole_make_install\n  when: guacamole_make['changed']\n\n- name: ldconfig\n  ansible.builtin.command: ldconfig\n  when: guacamole_make_install['changed']\n\n"
  },
  {
    "path": "ansible/roles/linux/guacamole/tasks/user.yml",
    "content": "- name: change guacadmin password\n  community.mysql.mysql_query:\n    login_host: \"localhost\"\n    login_port: \"3306\"\n    login_db: \"{{ guacamole_db }}\"\n    login_user: \"{{ guacamole_db_username }}\"\n    login_password: \"{{ guacamole_db_password }}\"\n    query: >\n      UPDATE guacamole_user set \n        password_salt=UNHEX('{{salt|upper}}'), \n        password_hash=UNHEX(SHA2(CONCAT('{{guacadmin_password}}', '{{salt|upper}}'), 256)), \n        password_date=CURRENT_TIMESTAMP \n      WHERE entity_id = 1;\n"
  },
  {
    "path": "ansible/roles/linux/guacamole/templates/guacamole.properties.j2",
    "content": "# Mysql infos\nmysql-hostname: localhost\nmysql-port: 3306\nmysql-database: {{guacamole_db}}\nmysql-username: {{guacamole_db_username}}\nmysql-password: {{guacamole_db_password}}\nmysql-ssl-mode: disabled\n\n# Hostname and port of guacamole proxy\nguacd-hostname: localhost\nguacd-port:     4822"
  },
  {
    "path": "ansible/roles/linux/guacamole/templates/guacd.conf.j2",
    "content": "[daemon]\npid_file = /var/run/guacd.pid\nlog_level = info\n\n[server]\nbind_host = 0.0.0.0\nbind_port = 4822\n"
  },
  {
    "path": "ansible/roles/linux/guacamole_create_connections/defaults/main.yml",
    "content": "guac_url: http://localhost:8080/guacamole\nguacadmin_username: guacadmin\nvnc_password: pouet"
  },
  {
    "path": "ansible/roles/linux/guacamole_create_connections/tasks/main.yml",
    "content": "- name: Create Local admin connections group \n  scicore.guacamole.guacamole_connections_group:\n    base_url: \"{{guac_url}}\"\n    auth_username: \"{{guacadmin_username}}\"\n    auth_password: \"{{guacadmin_password}}\"\n    group_name: \"{{domain_name}}-LOCAL\"\n\n# LOCAL ADMIN\n- name: Add Local RDP Admin connection\n  scicore.guacamole.guacamole_connection:\n    base_url: \"{{guac_url}}\"\n    rdp_domain: \".\"\n    auth_username: \"{{guacadmin_username}}\"\n    auth_password: \"{{guacadmin_password}}\"\n    connection_name: \"RDP-{{item.key}}-{{item.value.hostname}}-localadmin\"\n    protocol: \"rdp\"\n    hostname: \"{{hostvars[item.key].ansible_host}}\"\n    port: \"3389\"\n    username: \"{{admin_user}}\"\n    password: \"{{ item.value.local_admin_password }}\"\n    rdp_server_layout: \"{{layout}}\"\n    rdp_ignore_server_certs: true\n    validate_certs: false\n    max_connections: 4\n    group_name: \"{{domain_name}}-LOCAL\"\n  when: item.value.os | default('') in ['', 'windows'] and hostvars[item.key] is defined\n  with_dict: \"{{hosts}}\"\n\n- name: Add RDP local admin to list of connections\n  set_fact:\n    \"connection_list\": \"{{ connection_list | default([]) + ['RDP-' + item.key + '-' + item.value.hostname + '-localadmin']}}\"\n  with_dict: \"{{hosts}}\"\n\n- name: Add Local SSH connection\n  scicore.guacamole.guacamole_connection:\n    base_url: \"{{guac_url}}\"\n    auth_username: \"{{guacadmin_username}}\"\n    auth_password: \"{{guacadmin_password}}\"\n    connection_name: \"SSH-{{item.key}}-{{item.value.hostname}}-localadmin\"\n    protocol: \"ssh\"\n    hostname: \"{{hostvars[item.key].ansible_host}}\"\n    port: \"22\"\n    username: \"{{admin_user}}\"\n    password: \"{{ item.value.local_admin_password }}\"\n    validate_certs: false\n    max_connections: 4\n    group_name: \"{{domain_name}}-LOCAL\"\n  when: item.value.os is defined and item.value.os == \"linux\" and hostvars[item.key] is defined\n  with_dict: \"{{hosts}}\"\n\n- name: Add SSH local admin to list of connections\n  set_fact:\n    \"connection_list\": \"{{ connection_list | default([]) + ['SSH-' + item.key + '-' + item.value.hostname + '-localadmin']}}\"\n  with_dict: \"{{hosts}}\"\n\n# # VNC\n# - name: Create VNC connections group \n#   scicore.guacamole.guacamole_connections_group:\n#     base_url: \"{{guac_url}}\"\n#     auth_username: \"{{guacadmin_username}}\"\n#     auth_password: \"{{guacadmin_password}}\"\n#     group_name: \"{{domain_name}}-VNC\"\n# \n# - name: Add VNC connection\n#   scicore.guacamole.guacamole_connection:\n#     base_url: \"{{guac_url}}\"\n#     auth_username: \"{{guacadmin_username}}\"\n#     auth_password: \"{{guacadmin_password}}\"\n#     connection_name: \"VNC-{{item.key}}-{{item.value.hostname}}\"\n#     protocol: \"vnc\"\n#     hostname: \"{{hostvars[item.key].ansible_host}}\"\n#     port: \"5900\"\n#     username: \"\"\n#     password: \"{{ vnc_password }}\"\n#     group_name: \"{{domain_name}}-VNC\"\n#   when: item.value.os == \"windows\"\n#   with_dict: \"{{hosts}}\"\n# \n# - name: Add VNC  to list of connections\n#   set_fact:\n#     \"connection_list\": \"{{ connection_list | default([]) + ['VNC-' + item.key + '-' + item.value.hostname ]}}\"\n#   with_dict: \"{{hosts}}\"\n\n# Domain users\n- name: Create domain connections groups (one group by domain)\n  scicore.guacamole.guacamole_connections_group:\n    base_url: \"{{guac_url}}\"\n    auth_username: \"{{guacadmin_username}}\"\n    auth_password: \"{{guacadmin_password}}\"\n    group_name: \"{{domain_data.key}}\"\n  loop: \"{{ domains | dict2items }}\"\n  loop_control:\n    loop_var: domain_data\n\n- name: Iterate over users in each domain\n  include_tasks: users_iterate.yml\n  vars:\n    users_domain_name: \"{{domain_data.key}}\"\n    users: \"{{domain_data.value.users}}\"\n    hosts_list: \"{{hosts}}\"\n  loop: \"{{ domains | dict2items }}\"\n  loop_control:\n    loop_var: domain_data\n\n- name: Add guacamole user\n  scicore.guacamole.guacamole_user:\n    base_url: \"{{guac_url}}\"\n    auth_username: \"{{guacadmin_username}}\"\n    auth_password: \"{{guacadmin_password}}\"\n    username: \"{{ item.name }}\"\n    password: \"{{ item.pass }}\"\n    allowed_connections: \"{{connection_list |list}}\"\n    organization: company_bar\n  with_items:\n    - \"{{guacamole_users}}\"\n"
  },
  {
    "path": "ansible/roles/linux/guacamole_create_connections/tasks/users_hosts.yml",
    "content": "- name: \"User {{user_name}}\"\n  debug:\n    msg: \"Domain : {{user_domain_name}} | user : {{user_name}} | password: {{user_password}} | host: {{hosts_data.key}}\"\n  loop: \"{{ user_hosts_list | dict2items }}\"\n  loop_control:\n    loop_var: hosts_data\n  when: user_guacamole == \"yes\"\n\n- name: \"Create a connection group for {{user_name}}\"\n  scicore.guacamole.guacamole_connections_group:\n    base_url: \"{{guac_url}}\"\n    auth_username: \"{{guacadmin_username}}\"\n    auth_password: \"{{guacadmin_password}}\"\n    group_name: \"{{user_name}}\"\n    parent_group: \"{{user_domain_name}}\"\n  when: user_guacamole == \"yes\"\n\n- name: \"Add Local RDP connection for User : {{user_name}}\"\n  scicore.guacamole.guacamole_connection:\n    base_url: \"{{guac_url}}\"\n    rdp_domain: \"{{user_domain_name}}\"\n    auth_username: \"{{guacadmin_username}}\"\n    auth_password: \"{{guacadmin_password}}\"\n    connection_name: \"RDP-{{hosts_data.key}}-{{hosts_data.value.hostname}}-{{user_name}}\"\n    protocol: \"rdp\"\n    hostname: \"{{hostvars[hosts_data.key].ansible_host}}\"\n    port: \"3389\"\n    username: \"{{user_name}}\"\n    password: \"{{user_password}}\"\n    rdp_server_layout: \"{{layout}}\"\n    rdp_ignore_server_certs: true\n    validate_certs: false\n    max_connections: 4\n    group_name: \"{{user_name}}\"\n  loop: \"{{ user_hosts_list | dict2items }}\"\n  loop_control:\n    loop_var: hosts_data\n  when: >-\n    hostvars[hosts_data.key] is defined and\n    user_guacamole == \"yes\" and (hosts_data.value.os | default('') in ['', 'windows']) and (\n       (hosts_data.value.local_groups.get('Administrators', []) | default([]) | map('regex_replace', '.*\\\\\\\\', '') | list | intersect(user_groups) | length > 0)\n    or (hosts_data.value.local_groups.get('Remote Desktop Users', []) | default([]) | map('regex_replace', '.*\\\\\\\\', '') | list | intersect(user_groups) | length > 0)\n    or ((user_domain_name == hosts_data.value.domain) and (['Domain Admins']| list | intersect(user_groups) | length > 0))\n    or (hosts_data.value.local_groups.get('Administrators', []) | default([])  | map('regex_replace', '.*\\\\\\\\', '') | list | intersect([user_name]) | length > 0)\n    or (hosts_data.value.local_groups.get('Remote Desktop Users', []) | default([]) | map('regex_replace', '.*\\\\\\\\', '') | list | intersect([user_name]) | length > 0)\n    )\n\n- name: Add RDP user to list of connections\n  set_fact:\n    \"connection_list\": \"{{ connection_list | default([]) + ['RDP-' + hosts_data.key + '-' + hosts_data.value.hostname + '-' + user_name]}}\"\n  loop: \"{{ user_hosts_list | dict2items }}\"\n  loop_control:\n    loop_var: hosts_data\n  when: >-\n    hostvars[hosts_data.key] is defined and\n    user_guacamole == \"yes\" and (hosts_data.value.os | default('') in ['', 'windows']) and (\n       (hosts_data.value.local_groups.get('Administrators', []) | default([]) | map('regex_replace', '.*\\\\\\\\', '') | list | intersect(user_groups) | length > 0)\n    or (hosts_data.value.local_groups.get('Remote Desktop Users', []) | default([]) | map('regex_replace', '.*\\\\\\\\', '') | list | intersect(user_groups) | length > 0)\n    or ((user_domain_name == hosts_data.value.domain) and (['Domain Admins']| list | intersect(user_groups) | length > 0))\n    or (hosts_data.value.local_groups.get('Administrators', []) | default([])  | map('regex_replace', '.*\\\\\\\\', '') | list | intersect([user_name]) | length > 0)\n    or (hosts_data.value.local_groups.get('Remote Desktop Users', []) | default([]) | map('regex_replace', '.*\\\\\\\\', '') | list | intersect([user_name]) | length > 0)\n    )\n\n- name: \"Add Local SSH connection for User : {{user_name}}\"\n  scicore.guacamole.guacamole_connection:\n    base_url: \"{{guac_url}}\"\n    auth_username: \"{{guacadmin_username}}\"\n    auth_password: \"{{guacadmin_password}}\"\n    connection_name: \"SSH-{{hosts_data.key}}-{{hosts_data.value.hostname}}-{{user_name}}\"\n    protocol: \"ssh\"\n    hostname: \"{{hostvars[hosts_data.key].ansible_host}}\"\n    port: \"22\"\n    username: \"{{user_name}}\"\n    password: \"{{user_password}}\"\n    validate_certs: false\n    max_connections: 4\n    group_name: \"{{user_name}}\"\n  loop: \"{{ user_hosts_list | dict2items }}\"\n  loop_control:\n    loop_var: hosts_data\n  when: >-\n    hostvars[hosts_data.key] is defined and\n    user_guacamole == \"yes\" and (hosts_data.value.os is defined and hosts_data.value.os == \"linux\") and (\n       (hosts_data.value.local_groups.get('ssh', []) | default([]) | map('regex_replace', '.*\\\\\\\\', '') | list | intersect(user_groups) | length > 0)\n    or ((user_domain_name == hosts_data.value.domain) and (['Domain Admins']| list | intersect(user_groups) | length > 0))\n    or (hosts_data.value.local_groups.get('ssh', []) | default([]) | map('regex_replace', '.*\\\\\\\\', '') | list | intersect([user_name]) | length > 0)\n    )\n\n- name: Add SSH user to list of connections\n  set_fact:\n    \"connection_list\": \"{{ connection_list | default([]) + ['SSH-' + hosts_data.key + '-' + hosts_data.value.hostname + '-' + user_name]}}\"\n  loop: \"{{ user_hosts_list | dict2items }}\"\n  loop_control:\n    loop_var: hosts_data\n  when: >-\n    hostvars[hosts_data.key] is defined and\n    user_guacamole == \"yes\" and (hosts_data.value.os is defined and hosts_data.value.os == \"linux\") and (\n       (hosts_data.value.local_groups.get('ssh', []) | default([])| map('regex_replace', '.*\\\\\\\\', '') | list | intersect(user_groups) | length > 0)\n    or ((user_domain_name == hosts_data.value.domain) and (['Domain Admins']| list | intersect(user_groups) | length > 0))\n    or (hosts_data.value.local_groups.get('ssh', []) | default([]) | map('regex_replace', '.*\\\\\\\\', '') | list | intersect([user_name]) | length > 0)\n    )"
  },
  {
    "path": "ansible/roles/linux/guacamole_create_connections/tasks/users_iterate.yml",
    "content": "- name: Iterate over users in each domain\n  include_tasks: users_hosts.yml\n  vars:\n    user_domain_name: \"{{users_domain_name}}\"\n    user_name: \"{{users_data.key}}\"\n    user_password: \"{{users_data.value.password}}\"\n    user_groups: \"{{users_data.value.groups}}\"\n    user_hosts_list: \"{{hosts_list}}\"\n    user_guacamole: \"{{users_data.value.guacamole | default('yes')}}\"\n  loop: \"{{ users | dict2items }}\"\n  loop_control:\n    loop_var: users_data"
  },
  {
    "path": "ansible/roles/linux/php/handlers/main.yml",
    "content": "- name: reload apache\n  service:\n    name: apache2\n    state: reloaded"
  },
  {
    "path": "ansible/roles/linux/php/tasks/main.yml",
    "content": "- name: install php packages\n  apt: \n    update_cache: yes \n    state: latest\n    pkg:\n      - php\n      - php-gd\n      - php-mysql\n      - php-curl\n      - php-imap\n      - php-json\n      - php-ldap\n      - php-mbstring\n      - php-xml\n      - php-cli\n      - php-xmlrpc\n      - php-intl\n      - php-apcu\n      - php-cas\n      - php-zip\n      - php-bz2\n  notify: reload apache"
  },
  {
    "path": "ansible/roles/linux/proxy_server/defaults/main.yml",
    "content": "squid_port: \"3128\"\nip_range: \"192.168.56.1/24\"\nproxy_fqdn: \"proxy.sevenkingdoms.local\"\n"
  },
  {
    "path": "ansible/roles/linux/proxy_server/files/000-default.conf",
    "content": "<VirtualHost *:80>\n    ServerName squid\n    ServerAdmin admin@squid\n    DocumentRoot /var/www/html\n\n    <Directory /var/www/html>\n            Options FollowSymLinks\n            AllowOverride None\n            Require all granted\n    </Directory>\n</VirtualHost>"
  },
  {
    "path": "ansible/roles/linux/proxy_server/handlers/main.yml",
    "content": "- name: restart squid\n  ansible.builtin.service:\n    name: squid\n    state: restarted\n\n- name: restart apache\n  service:\n    name: apache2\n    state: restarted"
  },
  {
    "path": "ansible/roles/linux/proxy_server/tasks/main.yml",
    "content": "- name: update apt cache\n  apt: update_cache=yes\n\n- name: Install AD Packages\n  apt:\n    name:\n      - squid\n    state: present\n\n- name: setup squid config\n  ansible.builtin.template:\n    src: squid.conf.j2\n    dest: \"/etc/squid/squid.conf\"\n    owner: \"root\"\n    group: \"root\"\n    mode: \"644\"\n  notify:\n    - restart squid\n\n# WPAD serve\n- name: Install Apache\n  apt: \n    name: apache2\n    state: latest\n\n- name: Change Apache default vhost\n  copy:\n    src: 000-default.conf\n    dest: /etc/apache2/sites-available/000-default.conf\n    owner: \"root\"\n    group: \"root\"\n    force: yes\n    mode: 0644\n\n- name: setup wpad config\n  ansible.builtin.template:\n    src: wpad.dat.j2\n    dest: \"/var/www/html/wpad.dat\"\n    owner: \"root\"\n    group: \"root\"\n    mode: \"644\"\n\n- name: Start Apache service and enable\n  service: \n    name: apache2\n    state: started\n    enabled: true\n\n- name: Enable Apache mods\n  command: a2enmod {{ item }}\n  with_items:\n    - headers\n    - ssl\n    - rewrite\n  notify: restart apache"
  },
  {
    "path": "ansible/roles/linux/proxy_server/templates/squid.conf.j2",
    "content": "visible_hostname {{proxy_fqdn}}\nhttp_port 0.0.0.0:{{squid_port}}\n\n#################################### ACL ####################################\nacl all src all\nacl lan src {{ip_range}}\nacl Safe_ports port 80 # Port HTTP = Port 'sure'\nacl Safe_ports port 443 # Port HTTPS = Port 'sure'\n############################################################################\n\n# access only safe port\nhttp_access deny !Safe_ports\n# access lan only\nhttp_access deny !lan\n\n# the port in use in the proxy\nhttp_port {{squid_port}}\n"
  },
  {
    "path": "ansible/roles/linux/proxy_server/templates/wpad.dat.j2",
    "content": "function FindProxyForURL(url, host) {\n    if (host == \"127.0.0.1\" || isPlainHostName(host) || shExpMatch (host, \"({{proxy_fqdn}})\")) {\n        return \"DIRECT\";\n    }\n\n    return \"PROXY {{proxy_fqdn}}:3128\";\n}"
  },
  {
    "path": "ansible/roles/linux/tomcat/tasks/main.yml",
    "content": "- name: \"Update cache\"\n  ansible.builtin.apt:\n    update_cache: true\n    cache_valid_time: 86400\n\n- name: Install tomcat9\n  ansible.builtin.apt:\n    name: \n      - tomcat9\n    state: present"
  },
  {
    "path": "ansible/roles/localusers/tasks/main.yml",
    "content": "- name: \"Create local users\"\n  ansible.windows.win_user:\n    name: \"{{ item.key }}\"\n    password: \"{{ item.value.password }}\"\n    state: present\n    groups: \"{{ item.value.groups }}\"\n    password_never_expires: true\n    user_cannot_change_password: true\n    account_disabled: \"{{ item.value.disabled | default(false) }}\"\n  with_dict: \"{{ local_users }}\"\n"
  },
  {
    "path": "ansible/roles/logs_windows/defaults/main.yml",
    "content": "\nsysmon_download_url_base: \"https://download.sysinternals.com/files\"\nsysmon_install_location: \"c:\\\\sysmon\"\nsysmon_download_file: Sysmon\nfile_ext: .zip\nsysmon_config_url: \"https://raw.githubusercontent.com/SwiftOnSecurity/sysmon-config/master/sysmonconfig-export.xml\"\n\nwinlogbeat_service:\n  install_path_64: \"C:\\\\Program Files\\\\Elastic\\\\winlogbeat\"\n  install_path_32: \"C:\\\\Program Files (x86)\\\\Elastic\\\\winlogbeat\"\n  version: \"7.17.6\"\n  download: true"
  },
  {
    "path": "ansible/roles/logs_windows/files/sysmonconfig-export.xml",
    "content": "﻿<!--\n  sysmon-config | A Sysmon configuration focused on default high-quality event tracing and easy customization by the community\n  Source version:\t74 | Date: 2021-07-08\n  Source project:\thttps://github.com/SwiftOnSecurity/sysmon-config\n  Source license:\tCreative Commons Attribution 4.0 | You may privatize, fork, edit, teach, publish, or deploy for commercial use - with attribution in the text.\n\n  Fork version:\t<N/A>\n  Fork author:\t<N/A>\n  Fork project:\t<N/A>\n  Fork license:\t<N/A>\n\n  REQUIRED: Sysmon version 13 or higher (due to changes in syntax and bug-fixes)\n\thttps://docs.microsoft.com/en-us/sysinternals/downloads/sysmon\n\n  NOTE: To collect Sysmon logs centrally for free, see https://aka.ms/WEF | Command to allow log access to the Network Service:\n\twevtutil.exe sl Microsoft-Windows-Sysmon/Operational /ca:O:BAG:SYD:(A;;0xf0005;;;SY)(A;;0x5;;;BA)(A;;0x1;;;S-1-5-32-573)(A;;0x1;;;NS)\n\n  NOTE: Do not let the size and complexity of this configuration discourage you from customizing it or building your own.\n\tThis configuration is based around known, high-signal event tracing, and thus appears complicated, but it is only very\n\tdetailed. Significant effort over years has been invested in front-loading as much filtering as possible onto the\n\tclient. This is to make analysis of intrusions possible by hand, and to try to surface anomalous activity as quickly\n\tas possible to technicians armed only with Event Viewer. Its purpose is to democratize system monitoring for all organizations.\n\n  NOTE: Sysmon is NOT a whitelist solution or HIDS correlation engine, it is a computer change logging tool.\n\tDo NOT ignore everything possible. Sysmon's purpose is providing context during a threat or problem investigation. Legitimate\n\tprocesses are routinely used by threats - do not blindly exclude them. Additionally, be mindful of process-hollowing / imitation.\n\n  NOTE: By default this monitors DNS, which is extremely noisy. If you are starting out on your monitoring journey, just remove that section.\n\tYou can remove DNS events from Event Viewer screen by applying a 'Filter Current View' for event IDs of: -22\n\tAdditionally, if you want to monitor DNS, you should deploy client-side adblocking to reduce lookups. See the DNS section for info.\n\n  NOTE: This configuration is designed for PER-MACHINE installs of Chrome and OneDrive. That moves their binaries out of user-controlled folders.\n\tOtherwise, attackers could imitate these common applications, and bypass your logging. Below are silent upgrades you can do, no user impact:\n\t- https://docs.microsoft.com/en-us/onedrive/per-machine-installation\n\t- https://cloud.google.com/chrome-enterprise/browser/download/\n\t- As of 2021-02-16 there is no machine-level version of Microsoft Teams. The one provided copies itself to the user profile.\n\n  NOTE: Sysmon is not hardened against an attacker with admin rights. Additionally, this configuration offers an attacker, willing\n\tto study it, limited ways to evade some of the logging. If you are in a very high-threat environment, you should consider a broader,\n\tlog-most approach. However, in the vast majority of cases, an attacker will bumble through multiple behavioral traps which\n\tthis configuration monitors, especially in the first minutes.\n\n  NOTE: If you encounter unexplainable event inclusion/exclusion, you may have a second Sysmon instance installed under a different exe filename.\n\tTo clear this, try downloading the latest version and uninstalling with -u force. If it hangs, kill the processes and run it again to cleanup.\n\n  TECHNICAL:\n  - Run sysmon.exe -? for a briefing on Sysmon configuration.\n  - Sysmon XML cannot use the AMPERSAND sign. Replace it with this: &amp;\n  - Sysmon 8+ can track which rule caused an event to be logged through the \"RuleName\" field.\n  - If you only specify exclude for a filtering subsection, everything in that subsection is logged by default.\n  - Some Sysmon monitoring abilities are not meant for widely deployed general-purpose use due to performance impact. Depends on environment.\n  - Duplicate or overlapping \"Include\" rules do not result in duplicate events being logged.\n  - All characters enclosed by XML tags are always interpreted literally. Sysmon does not support wildcards (*), alternate characters, or RegEx.\n  - In registry events, the value name is appended to the full key path with a \"\\\" delimiter. Default key values are named \"\\(Default)\"\n  - \"Image\" is a technical term for a compiled binary file like an EXE or DLL. Also, it can match just the filename, or entire path.\n  - \"ProcessGuid\" and \"LoginGuid\" are not random, they contain some embedded information. https://gist.github.com/mattifestation/0102042160c9a60b2b847378c0ef70b4\n\n  FILTERING: Filter conditions available for use are: is,is not,contains,contains any,contains all,excludes,excludes any,excludes all,begin with,end with,less than,more than,image\n  - The \"image\" filter is usable on any field. Same as \"is\" but can either match entire string, or only the text after last \"\\\". Credit: @mattifestation\n\n-->\n\n<Sysmon schemaversion=\"4.50\">\n\t<!--SYSMON META CONFIG-->\n\t<HashAlgorithms>md5,sha256,IMPHASH</HashAlgorithms> <!-- Both MD5 and SHA256 are the industry-standard algorithms. Remove IMPHASH if you do not use DLL import fingerprinting. -->\n\t<CheckRevocation/> <!-- Check loaded drivers, log if their code-signing certificate has been revoked, in case malware stole one to sign a kernel driver -->\n\n\t<!-- <ImageLoad/> --> <!-- Would manually force-on ImageLoad monitoring, even without configuration below. Included only documentation. -->\n\t<!-- <ProcessAccessConfig/> --> <!-- Would manually force-on ProcessAccess monitoring, even without configuration below. Included only documentation. -->\n\t<!-- <PipeMonitoringConfig/> --> <!-- Would manually force-on PipeCreated / PipeConnected events, even without configuration below. Included only documentation. -->\n\t<!-- <ArchiveDirectory> -->\n\n\t<EventFiltering>\n\n\t<!--SYSMON EVENT ID 1 : PROCESS CREATION [ProcessCreate]-->\n\t\t<!--COMMENT:\tAll processes launched will be logged, except for what matches a rule below. It's best to be as specific as possible,\n\t\t\tto avoid user-mode executables imitating other process names to avoid logging, or if malware drops files in an existing directory.\n\t\t\tUltimately, you must weigh CPU time checking many detailed rules, against the risk of malware exploiting the blindness created.\n\t\t\tBeware of Masquerading, where attackers imitate the names and paths of legitimate tools. Ideally, you'd use both file path and\n\t\t\tcode signatures to validate, but Sysmon does not support that. Look into AppLocker/WindowsDeviceGuard for whitelisting support. -->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessID, Image, FileVersion, Description, Product, Company, CommandLine, CurrentDirectory, User, LogonGuid, LogonId, TerminalSessionId, IntegrityLevel, Hashes, ParentProcessGuid, ParentProcessId, ParentImage, ParentCommandLine, RuleName-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ProcessCreate onmatch=\"exclude\">\n\t\t\t<!--SECTION: Microsoft Windows-->\n\t\t\t<CommandLine condition=\"begin with\"> \"C:\\Windows\\system32\\wermgr.exe\" \"-queuereporting_svc\" </CommandLine> <!--Windows:Windows error reporting/telemetry-->\n\t\t\t<CommandLine condition=\"begin with\">C:\\Windows\\system32\\DllHost.exe /Processid</CommandLine> <!--Windows-->\n\t\t\t<CommandLine condition=\"begin with\">C:\\Windows\\system32\\wbem\\wmiprvse.exe -Embedding</CommandLine> <!--Windows: WMI provider host-->\n\t\t\t<CommandLine condition=\"begin with\">C:\\Windows\\system32\\wbem\\wmiprvse.exe -secured -Embedding</CommandLine> <!--Windows: WMI provider host-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\wermgr.exe -upload</CommandLine> <!--Windows:Windows error reporting/telemetry-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\SearchIndexer.exe /Embedding</CommandLine> <!--Windows: Search Indexer-->\n\t\t\t<CommandLine condition=\"is\">C:\\windows\\system32\\wermgr.exe -queuereporting</CommandLine> <!--Windows:Windows error reporting/telemetry-->\n\t\t\t<CommandLine condition=\"is\">\\??\\C:\\Windows\\system32\\autochk.exe *</CommandLine> <!--Microsoft:Bootup: Auto Check Utility-->\n\t\t\t<CommandLine condition=\"is\">\\SystemRoot\\System32\\smss.exe</CommandLine> <!--Microsoft:Bootup: Windows Session Manager-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\RuntimeBroker.exe -Embedding</CommandLine> <!--Windows:Apps permissions [ https://fossbytes.com/runtime-broker-process-windows-10/ ] -->\n\t\t\t<Image condition=\"is\">C:\\Program Files (x86)\\Common Files\\microsoft shared\\ink\\TabTip32.exe</Image> <!--Windows: Touch Keyboard and Handwriting Panel Helper-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\System32\\TokenBrokerCookies.exe</Image> <!--Windows: SSO sign-in assistant for MicrosoftOnline.com-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\System32\\plasrv.exe</Image> <!--Windows: Performance Logs and Alerts DCOM Server-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\System32\\wifitask.exe</Image> <!--Windows: Wireless Background Task-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\CompatTelRunner.exe</Image> <!--Windows: Customer Experience Improvement-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\PrintIsolationHost.exe</Image> <!--Windows: Printing-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\SppExtComObj.Exe</Image> <!--Windows: KMS activation-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\audiodg.exe</Image> <!--Windows: Launched constantly-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\conhost.exe</Image> <!--Windows: Command line interface host process-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\mobsync.exe</Image> <!--Windows: Network file syncing-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\musNotification.exe</Image> <!--Windows: Update pop-ups-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\musNotificationUx.exe</Image> <!--Windows: Update pop-ups-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\powercfg.exe</Image> <!--Microsoft:Power configuration management-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\sndVol.exe</Image> <!--Windows: Volume control-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\sppsvc.exe</Image> <!--Windows: Software Protection Service-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\wbem\\WmiApSrv.exe</Image> <!--Windows: WMI performance adapter host process-->\n\t\t\t<IntegrityLevel condition=\"is\">AppContainer</IntegrityLevel> <!--Windows: Don't care about sandboxed processes right now. Will need to revisit this decision.-->\n\t\t\t<ParentCommandLine condition=\"begin with\">%%SystemRoot%%\\system32\\csrss.exe ObjectDirectory=\\Windows</ParentCommandLine> <!--Windows:CommandShell: Triggered when programs use the command shell, but doesn't provide attribution for what caused it-->\n\t\t\t<ParentCommandLine condition=\"is\">C:\\windows\\system32\\wermgr.exe -queuereporting</ParentCommandLine> <!--Windows:Windows error reporting/telemetry-->\n\t\t\t<CommandLine condition=\"is\">C:\\WINDOWS\\system32\\devicecensus.exe UserCxt</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\usocoreworker.exe -Embedding</CommandLine>\n\t\t\t<ParentImage condition=\"is\">C:\\Windows\\system32\\SearchIndexer.exe</ParentImage> <!--Windows:Search: Launches many uninteresting sub-processes-->\n\t\t\t<!--SECTION: Windows:svchost-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k appmodel -s StateRepository</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k appmodel -p -s camsvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k appmodel</CommandLine> <!--Windows 10-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k appmodel -p -s tiledatamodelsvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k camera -s FrameServer</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k dcomlaunch -s LSM</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k dcomlaunch -s PlugPlay</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k defragsvc</CommandLine> <!--Windows defragmentation-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k devicesflow -s DevicesFlowUserSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k imgsvc</CommandLine> <!--Microsoft:The Windows Image Acquisition Service-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localService -s EventSystem</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localService -s bthserv</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k LocalService -p -s BthAvctpSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localService -s nsi</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localService -s w32Time</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceAndNoImpersonation</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted -s Dhcp</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted -s EventLog</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted -s TimeBrokerSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted -s WFDSConMgrSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted -s BTAGService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\svchost.exe -k LocalSystemNetworkRestricted -p -s NcbService</CommandLine> <!--Win10:1903:Network Connection Broker-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceAndNoImpersonation -s SensrSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceAndNoImpersonation -p -s SSDPSRV</CommandLine> <!--Windows:SSDP [ https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNoNetwork</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -p -s WPDBusEnum</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -p -s fhsvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s DeviceAssociationService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s NcbService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s SensorService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s TabletInputService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s UmRdpService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s WPDBusEnum</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -p -s NgcSvc</CommandLine> <!--Microsoft:Passport--> \n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted -p -s NgcCtnrSvc</CommandLine> <!--Microsoft:Passport Container--> \n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceAndNoImpersonation -s SCardSvr</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -p -s wuauserv</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\svchost.exe -k netsvcs -p -s SessionEnv</CommandLine> <!--Windows:Remote desktop configuration-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s WdiSystemHost</CommandLine> <!--Windows: Diagnostic System Host [ http://www.blackviper.com/windows-services/diagnostic-system-host/ ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\svchost.exe -k localSystemNetworkRestricted -p -s WdiSystemHost</CommandLine> <!--Windows: Diagnostic System Host [ http://www.blackviper.com/windows-services/diagnostic-system-host/ ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted</CommandLine> <!--Windows-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -p -s wlidsvc</CommandLine> <!--Windows: Windows Live Sign-In Assistant [ https://www.howtogeek.com/howto/30348/what-are-wlidsvc.exe-and-wlidsvcm.exe-and-why-are-they-running/ ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -p -s ncaSvc</CommandLine> <!--Windows: Network Connectivity Assistant [ http://www.blackviper.com/windows-services/network-connectivity-assistant/ ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s BDESVC</CommandLine> <!--Windows:Network: BitLocker Drive Encryption-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\svchost.exe -k netsvcs -p -s BDESVC</CommandLine> <!--Microsoft:Win10:1903:Network: BitLocker Drive Encryption-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -p -s BITS</CommandLine> <!--Windows:Network: Background Intelligent File Transfer (BITS) -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s BITS</CommandLine> <!--Windows:Network: Background Intelligent File Transfer (BITS) -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s CertPropSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s DsmSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -p -s Appinfo</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s Gpsvc</CommandLine> <!--Windows:Network: Group Policy -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s ProfSvc</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s SENS</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s SessionEnv</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s Themes</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s Winmgmt</CommandLine> <!--Windows: Windows Management Instrumentation (WMI) -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService -p -s DoSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService -s Dnscache</CommandLine> <!--Windows:Network: DNS caching, other uses -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService -s LanmanWorkstation</CommandLine> <!--Windows:Network: \"Workstation\" service, used for SMB file-sharing connections and RDP-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService -s NlaSvc</CommandLine> <!--Windows:Network: Network Location Awareness-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService -s TermService</CommandLine> <!--Windows:Network: Terminal Services (RDP)-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkServiceNetworkRestricted</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k rPCSS</CommandLine> <!--Windows Services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k secsvcs</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k swprv</CommandLine> <!--Microsoft:Software Shadow Copy Provider-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k unistackSvcGroup</CommandLine> <!--Windows 10-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k utcsvc</CommandLine> <!--Windows Services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k wbioSvcGroup</CommandLine> <!--Windows Services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k werSvcGroup</CommandLine> <!--Windows: ErrorReporting-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k wusvcs -p -s WaaSMedicSvc</CommandLine> <!--Windows: Update Medic Service [ https://www.thewindowsclub.com/windows-update-medic-service ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\svchost.exe -k wsappx -p -s ClipSVC</CommandLine> <!--Windows:Apps: Client License Service-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k wsappx -p -s AppXSvc</CommandLine> <!--Windows:Apps: AppX Deployment Service-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k wsappx -s ClipSVC</CommandLine> <!--Windows:Apps: Client License Service-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k wsappx</CommandLine> <!--Windows:Apps [ https://www.howtogeek.com/320261/what-is-wsappx-and-why-is-it-running-on-my-pc/ ] -->\n\t\t\t<ParentCommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs</ParentCommandLine> <!--Windows: Network services: Spawns Consent.exe-->\n\t\t\t<ParentCommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted</ParentCommandLine> <!--Windows-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\deviceenroller.exe /c /AutoEnrollMDM</CommandLine> <!--Windows: AzureAD device enrollment agent-->\n\t\t\t<!--SECTION: Microsoft:Edge-->\n\t\t\t<CommandLine condition=\"begin with\">\"C:\\Program Files (x86)\\Microsoft\\Edge Dev\\Application\\msedge.exe\" --type=</CommandLine>\n\t\t\t<!--SECTION: Microsoft:dotNet-->\n\t\t\t<CommandLine condition=\"begin with\">C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\ngen.exe</CommandLine> <!--Microsoft:DotNet-->\n\t\t\t<CommandLine condition=\"begin with\">C:\\WINDOWS\\Microsoft.NET\\Framework64\\v4.0.30319\\Ngen.exe</CommandLine> <!--Microsoft:DotNet-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\mscorsvw.exe</Image> <!--Microsoft:DotNet-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\mscorsvw.exe</Image> <!--Microsoft:DotNet-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\Microsoft.Net\\Framework64\\v3.0\\WPF\\PresentationFontCache.exe</Image> <!--Windows: Font cache service-->\n\t\t\t<ParentCommandLine condition=\"contains\">C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\ngentask.exe</ParentCommandLine>\n\t\t\t<ParentImage condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\mscorsvw.exe</ParentImage> <!--Microsoft:DotNet-->\n\t\t\t<ParentImage condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\ngentask.exe</ParentImage> <!--Microsoft:DotNet-->\n\t\t\t<ParentImage condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\mscorsvw.exe</ParentImage> <!--Microsoft:DotNet-->\n\t\t\t<ParentImage condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\ngentask.exe</ParentImage> <!--Microsoft:DotNet: Spawns thousands of ngen.exe processes-->\n\t\t\t<!--SECTION: Microsoft:Office-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Microsoft Office\\Office16\\MSOSYNC.EXE</Image> <!--Microsoft:Office: Background process for SharePoint/Office365 connectivity-->\n\t\t\t<Image condition=\"is\">C:\\Program Files (x86)\\Microsoft Office\\Office16\\MSOSYNC.EXE</Image> <!--Microsoft:Office: Background process for SharePoint/Office365 connectivity-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Common Files\\Microsoft Shared\\OfficeSoftwareProtectionPlatform\\OSPPSVC.EXE</Image> <!--Microsoft:Office: Licensing service-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Microsoft Office\\Office16\\msoia.exe</Image> <!--Microsoft:Office: Telemetry collector-->\n\t\t\t<Image condition=\"is\">C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\officebackgroundtaskhandler.exe</Image>\n\t\t\t<!--SECTION: Microsoft:Office:Click2Run-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Common Files\\Microsoft Shared\\ClickToRun\\OfficeC2RClient.exe</Image> <!--Microsoft:Office: Background process-->\n\t\t\t<ParentImage condition=\"is\">C:\\Program Files\\Common Files\\Microsoft Shared\\ClickToRun\\OfficeClickToRun.exe</ParentImage> <!--Microsoft:Office: Background process-->\n\t\t\t<ParentImage condition=\"is\">C:\\Program Files\\Common Files\\Microsoft Shared\\ClickToRun\\OfficeC2RClient.exe</ParentImage> <!--Microsoft:Office: Background process-->\n\t\t\t<!--SECTION: Windows: Media player-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Windows Media Player\\wmpnscfg.exe</Image> <!--Windows: Windows Media Player Network Sharing Service Configuration Application-->\n\t\t\t<!--SECTION: Google-->\n\t\t\t<CommandLine condition=\"begin with\">\"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe\" --type=</CommandLine> <!--Google:Chrome: massive command-line arguments-->\n\t\t\t<CommandLine condition=\"begin with\">\"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --type=</CommandLine> <!--Google:Chrome: massive command-line arguments-->\n\t\t</ProcessCreate>\n\t</RuleGroup>\n\t\n\t<!--SYSMON EVENT ID 2 : FILE CREATION TIME RETROACTIVELY CHANGED IN THE FILESYSTEM [FileCreateTime]-->\n\t\t<!--COMMENT:\t[ https://attack.mitre.org/wiki/Technique/T1099 ] -->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, TargetFilename, CreationUtcTime, PreviousCreationUtcTime-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<FileCreateTime onmatch=\"include\">\n\t\t\t<Image name=\"T1099\" condition=\"begin with\">C:\\Users</Image> <!--Look for timestomping in user area, usually nothing should be doing that here-->\n\t\t\t<TargetFilename name=\"T1099\" condition=\"end with\">.exe</TargetFilename> <!--Look for backdated executables anywhere-->\n\t\t\t<Image name=\"T1099\" condition=\"begin with\">\\Device\\HarddiskVolumeShadowCopy</Image> <!--Nothing should be written here | Credit: @SBousseaden [ https://twitter.com/SBousseaden/status/1133030955407630336 ] -->\n\t\t</FileCreateTime>\n\t</RuleGroup>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<FileCreateTime onmatch=\"exclude\">\n\t\t\t<Image condition=\"image\">OneDrive.exe</Image> <!--OneDrive constantly changes file times-->\n\t\t\t<Image condition=\"image\">C:\\Windows\\system32\\backgroundTaskHost.exe</Image>\n\t\t\t<Image condition=\"contains\">setup</Image> <!--Ignore setups-->\n\t\t\t<Image condition=\"contains\">install</Image> <!--Ignore setups-->\n\t\t\t<Image condition=\"contains\">Update\\</Image> <!--Ignore setups-->\n\t\t\t<Image condition=\"end with\">redist.exe</Image> <!--Ignore setups-->\n\t\t\t<Image condition=\"is\">msiexec.exe</Image> <!--Ignore setups-->\n\t\t\t<Image condition=\"is\">TrustedInstaller.exe</Image> <!--Ignore setups-->\n\t\t\t<TargetFilename condition=\"contains\">\\NVIDIA\\NvBackend\\ApplicationOntology\\</TargetFilename> <!--NVIDIA GeForce Experience Application Ontology, 1000's of events in user profile-->\n\t\t</FileCreateTime>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 3 : NETWORK CONNECTION INITIATED [NetworkConnect]-->\n\t\t<!--COMMENT:\tBy default this configuration takes a very conservative approach to network logging, limited to only extremely high-signal events.-->\n\t\t<!--COMMENT:\t[ https://attack.mitre.org/wiki/Command_and_Control ] [ https://attack.mitre.org/wiki/Exfiltration ] [ https://attack.mitre.org/wiki/Lateral_Movement ] -->\n\t\t<!--TECHNICAL:\tFor the DestinationHostname, Sysmon uses the GetNameInfo API, which will often not have any information, and may just be a CDN. This is NOT reliable for filtering.-->\n\t\t<!--TECHNICAL:\tFor the DestinationPortName, Sysmon uses the GetNameInfo API for the friendly name of ports you see in logs.-->\n\t\t<!--TECHNICAL:\tThese exe do not initiate their connections, and thus includes do not work in this section: BITSADMIN NLTEST-->\n\t\t\n\t\t<!-- https://www.first.org/resources/papers/conf2017/APT-Log-Analysis-Tracking-Attack-Tools-by-Audit-Policy-and-Sysmon.pdf -->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, User, Protocol, Initiated, SourceIsIpv6, SourceIp, SourceHostname, SourcePort, SourcePortName, DestinationIsIpV6, DestinationIp, DestinationHostname, DestinationPort, DestinationPortName-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<NetworkConnect onmatch=\"include\">\n\t\t\t<!--Suspicious sources for network-connecting binaries-->\n\t\t\t<Image name=\"Usermode\" condition=\"begin with\">C:\\Users</Image> <!--Tools downloaded by users can use other processes for networking, but this is a very valuable indicator.-->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">C:\\Recycle</Image> <!--Nothing should operate from the RecycleBin locations.-->\n\t\t\t<Image condition=\"begin with\">C:\\ProgramData</Image> <!--Normally, network communications should be sourced from \"Program Files\" not from ProgramData, something to look at-->\n\t\t\t<Image condition=\"begin with\">C:\\Windows\\Temp</Image> <!--Suspicious anything would communicate from the system-level temp directory-->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">\\</Image> <!--Devices and VSC shouldn't be executing changes | Credit: @SBousseaden @ionstorm @neu5ron @PerchedSystems [ https://twitter.com/SwiftOnSecurity/status/1133167323991486464 ] -->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">C:\\perflogs</Image> <!-- Credit @blu3_team [ https://blu3-team.blogspot.com/2019/05/netconn-from-suspicious-directories.html ] -->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">C:\\intel</Image> <!-- Credit @blu3_team [ https://blu3-team.blogspot.com/2019/05/netconn-from-suspicious-directories.html ] -->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">C:\\Windows\\fonts</Image> <!-- Credit @blu3_team [ https://blu3-team.blogspot.com/2019/05/netconn-from-suspicious-directories.html ] -->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">C:\\Windows\\system32\\config</Image> <!-- Credit @blu3_team [ https://blu3-team.blogspot.com/2019/05/netconn-from-suspicious-directories.html ] -->\n\t\t\t<!--Suspicious Windows tools-->\n\t\t\t<Image condition=\"image\">at.exe</Image> <!--Windows: Remote task scheduling, removed in Win10 | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">certutil.exe</Image> <!--Windows: Certificate tool can contact outbound | Credit @ion-storm @FVT [ https://twitter.com/FVT/status/834433734602530817 ] -->\n\t\t\t<Image condition=\"image\">cmd.exe</Image> <!--Windows: Remote command prompt-->\n\t\t\t<Image condition=\"image\">cmstp.exe</Image> <!--Windows: Connection manager profiles can launch executables from WebDAV [ https://twitter.com/NickTyrer/status/958450014111633408 ] | Credit @NickTyrer @Oddvarmoe @KyleHanslovan @subTee -->\n\t\t\t<Image condition=\"image\">cscript.exe</Image> <!--WindowsScriptingHost: | Credit @Cyb3rOps [ https://gist.github.com/Neo23x0/a4b4af9481e01e749409 ] -->\n\t\t\t<Image condition=\"image\">driverquery.exe</Image> <!--Windows: Remote recognisance of system configuration, oudated/vulnerable drivers -->\n\t\t\t<Image condition=\"image\">dsquery.exe</Image> <!--Microsoft: Query Active Directory -->\n\t\t\t<Image condition=\"image\">hh.exe</Image> <!--Windows: HTML Help Executable, opens CHM files -->\n\t\t\t<Image condition=\"image\">infDefaultInstall.exe</Image> <!--Microsoft: [ https://github.com/huntresslabs/evading-autoruns ] | Credit @KyleHanslovan -->\n\t\t\t<Image condition=\"image\">java.exe</Image> <!--Java: Monitor usage of vulnerable application and init from JAR files | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">javaw.exe</Image> <!--Java: Monitor usage of vulnerable application and init from JAR files -->\n\t\t\t<Image condition=\"image\">javaws.exe</Image> <!--Java: Monitor usage of vulnerable application and init from JAR files -->\n\t\t\t<Image condition=\"image\">mmc.exe</Image> <!--Windows: -->\n\t\t\t<Image condition=\"image\">msbuild.exe</Image> <!--Windows: [ https://www.hybrid-analysis.com/sample/a314f6106633fba4b70f9d6ddbee452e8f8f44a72117749c21243dc93c7ed3ac?environmentId=100 ] -->\n\t\t\t<Image condition=\"image\">mshta.exe</Image> <!--Windows: HTML application executes scripts without IE protections | Credit @ion-storm [ https://en.wikipedia.org/wiki/HTML_Application ] -->\n\t\t\t<Image condition=\"image\">msiexec.exe</Image> <!--Windows: Can install from http:// paths | Credit @vector-sec -->\n\t\t\t<Image condition=\"image\">nbtstat.exe</Image> <!--Windows: NetBIOS statistics, attackers use to enumerate local network -->\n\t\t\t<Image condition=\"image\">net.exe</Image> <!--Windows: Note - May not detect anything, net.exe is a front-end to lower APIs | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">net1.exe</Image> <!--Windows: Launched by \"net.exe\", but it may not detect connections either -->\n\t\t\t<Image condition=\"image\">notepad.exe</Image> <!--Windows: [ https://secrary.com/ReversingMalware/CoinMiner/ ] [ https://blog.cobaltstrike.com/2013/08/08/why-is-notepad-exe-connecting-to-the-internet/ ] -->\n\t\t\t<Image condition=\"image\">nslookup.exe</Image> <!--Windows: Retrieve data over DNS -->\n\t\t\t<Image condition=\"image\">powershell.exe</Image> <!--Windows: PowerShell interface-->\n\t\t\t<Image condition=\"image\">qprocess.exe</Image> <!--Windows: [ https://www.first.org/resources/papers/conf2017/APT-Log-Analysis-Tracking-Attack-Tools-by-Audit-Policy-and-Sysmon.pdf ] -->\n\t\t\t<Image condition=\"image\">qwinsta.exe</Image> <!--Windows: Query remote sessions | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">qwinsta.exe</Image> <!--Windows: Remotely query login sessions on a server or workstation | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">reg.exe</Image> <!--Windows: Remote Registry editing ability | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">regsvcs.exe</Image> <!--Windows: [ https://www.hybrid-analysis.com/sample/3f94d7080e6c5b8f59eeecc3d44f7e817b31562caeba21d02ad705a0bfc63d67?environmentId=100 ] -->\n\t\t\t<Image condition=\"image\">regsvr32.exe</Image> <!--Windows: [ https://subt0x10.blogspot.com/2016/04/bypass-application-whitelisting-script.html ] -->\n\t\t\t<Image condition=\"image\">rundll32.exe</Image> <!--Windows: [ https://blog.cobaltstrike.com/2016/07/22/why-is-rundll32-exe-connecting-to-the-internet/ ] -->\n\t\t\t<Image condition=\"image\">rwinsta.exe</Image> <!--Windows: Disconnect remote sessions | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">sc.exe</Image> <!--Windows: Remotely change Windows service settings | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">schtasks.exe</Image> <!--Windows: Command-line interface to local and remote tasks -->\n\t\t\t<Image condition=\"image\">taskkill.exe</Image> <!--Windows: Kill processes, has remote ability -->\n\t\t\t<Image condition=\"image\">tasklist.exe</Image> <!--Windows: List processes, has remote ability -->\n\t\t\t<Image condition=\"image\">wmic.exe</Image> <!--WindowsManagementInstrumentation: Credit @Cyb3rOps [ https://gist.github.com/Neo23x0/a4b4af9481e01e749409 ] -->\n\t\t\t<Image condition=\"image\">wscript.exe</Image> <!--WindowsScriptingHost: | Credit @arekfurt -->\n\t\t\t<!--Relevant 3rd Party Tools-->\n\t\t\t<Image condition=\"image\">nc.exe</Image> <!-- Nmap's modern version of netcat [ https://nmap.org/ncat/guide/index.html#ncat-overview ] [ https://securityblog.gr/1517/create-backdoor-in-windows-with-ncat/ ] -->\n\t\t\t<Image condition=\"image\">ncat.exe</Image> <!-- Nmap's modern version of netcat [ https://nmap.org/ncat/guide/index.html#ncat-overview ] [ https://securityblog.gr/1517/create-backdoor-in-windows-with-ncat/ ] -->\n\t\t\t<Image condition=\"image\">psexec.exe</Image> <!--Sysinternals:PsExec client side | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">psexesvc.exe</Image> <!--Sysinternals:PsExec server side | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">tor.exe</Image> <!--Tor [ https://www.hybrid-analysis.com/sample/800bf028a23440134fc834efc5c1e02cc70f05b2e800bbc285d7c92a4b126b1c?environmentId=100 ] -->\n\t\t\t<Image condition=\"image\">vnc.exe</Image> <!-- VNC client | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">vncservice.exe</Image> <!-- VNC server | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">vncviewer.exe</Image> <!-- VNC client | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">winexesvc.exe</Image> <!-- Winexe service executable | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">nmap.exe</Image>\n\t\t\t<Image condition=\"image\">psinfo.exe</Image>\n\t\t\t<!--Ports: Suspicious-->\n\t\t\t<DestinationPort name=\"SSH\" condition=\"is\">22</DestinationPort> <!--SSH protocol, monitor admin connections-->\n\t\t\t<DestinationPort name=\"Telnet\" condition=\"is\">23</DestinationPort> <!--Telnet protocol, monitor admin connections, insecure-->\n\t\t\t<DestinationPort name=\"SMTP\" condition=\"is\">25</DestinationPort> <!--SMTP mail protocol port, insecure, used by threats-->\n\t\t\t<DestinationPort name=\"IMAP\" condition=\"is\">143</DestinationPort> <!--IMAP mail protocol port, insecure, used by threats-->\n\t\t\t<DestinationPort name=\"RDP\" condition=\"is\">3389</DestinationPort> <!--Windows:RDP: Monitor admin connections-->\n\t\t\t<DestinationPort name=\"VNC\" condition=\"is\">5800</DestinationPort> <!--VNC protocol: Monitor admin connections, often insecure, using hard-coded admin password-->\n\t\t\t<DestinationPort name=\"VNC\" condition=\"is\">5900</DestinationPort> <!--VNC protocol Monitor admin connections, often insecure, using hard-coded admin password-->\n\t\t\t<DestinationPort name=\"Alert,Metasploit\" condition=\"is\">444</DestinationPort>\n\t\t\t<!--Ports: Proxy-->\n\t\t\t<DestinationPort name=\"Proxy\" condition=\"is\">1080</DestinationPort> <!--Socks proxy port | Credit @ion-storm-->\n\t\t\t<DestinationPort name=\"Proxy\" condition=\"is\">3128</DestinationPort> <!--Socks proxy port | Credit @ion-storm-->\n\t\t\t<DestinationPort name=\"Proxy\" condition=\"is\">8080</DestinationPort> <!--Socks proxy port | Credit @ion-storm-->\n\t\t\t<!--Ports: Tor-->\n\t\t\t<DestinationPort name=\"Tor\" condition=\"is\">1723</DestinationPort> <!--Tor protocol [ https://attack.mitre.org/wiki/Technique/T1090 ] | Credit @ion-storm-->\n\t\t\t<DestinationPort name=\"Tor\" condition=\"is\">9001</DestinationPort> <!--Tor protocol [ http://www.computerworlduk.com/tutorial/security/tor-enterprise-2016-blocking-malware-darknet-use-rogue-nodes-3633907/ ] -->\n\t\t\t<DestinationPort name=\"Tor\" condition=\"is\">9030</DestinationPort> <!--Tor protocol [ http://www.computerworlduk.com/tutorial/security/tor-enterprise-2016-blocking-malware-darknet-use-rogue-nodes-3633907/ ] -->\n\t\t</NetworkConnect>\n\t</RuleGroup>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<NetworkConnect onmatch=\"exclude\">\n\t\t\t<!--SECTION: Microsoft-->\n\t\t\t<Image condition=\"begin with\">C:\\ProgramData\\Microsoft\\Windows Defender\\Platform\\</Image>\n\t\t\t<Image condition=\"end with\">AppData\\Local\\Microsoft\\Teams\\current\\Teams.exe</Image> <!--Microsoft: Teams-->\n\t\t\t<DestinationHostname condition=\"end with\">.microsoft.com</DestinationHostname> <!--Microsoft:Update delivery-->\n\t\t\t<DestinationHostname condition=\"end with\">microsoft.com.akadns.net</DestinationHostname> <!--Microsoft:Update delivery-->\n\t\t\t<DestinationHostname condition=\"end with\">microsoft.com.nsatc.net</DestinationHostname> <!--Microsoft:Update delivery-->\n\t\t\t<!--OCSP known addresses-->\n\t\t\t<DestinationIp condition=\"is\">23.4.43.27</DestinationIp> <!--Digicert [ https://otx.alienvault.com/indicator/ip/23.4.43.27 ] -->\n\t\t\t<DestinationIp condition=\"is\">72.21.91.29</DestinationIp> <!--Digicert [ https://otx.alienvault.com/indicator/ip/72.21.91.29 ] -->\n\t\t\t<!--Section: Loopback Addresses-->\n\t\t\t<DestinationIp condition=\"is\">127.0.0.1</DestinationIp> <!--Credit @ITProPaul-->\n\t\t\t<DestinationIp condition=\"begin with\">fe80:0:0:0</DestinationIp> <!--Credit @ITProPaul-->\n\t\t</NetworkConnect>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 4 : RESERVED FOR SYSMON SERVICE STATUS MESSAGES-->\n\n\t\t<!--DATA: UtcTime, State, Version, SchemaVersion-->\n\t\t<!--Cannot be filtered.-->\n\n\t<!--SYSMON EVENT ID 5 : PROCESS ENDED [ProcessTerminate]-->\n\t\t<!--COMMENT:\tUseful data in building infection timelines.-->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ProcessTerminate onmatch=\"include\">\n\t\t\t<Image condition=\"begin with\">C:\\Users</Image> <!--Process terminations by user binaries-->\n\t\t\t<Image condition=\"begin with\">\\</Image> <!--Devices and VSC shouldn't be executing changes | Credit: @SBousseaden @ionstorm @neu5ron @PerchedSystems [ https://twitter.com/SwiftOnSecurity/status/1133167323991486464 ] -->\n\t\t</ProcessTerminate>\n\t</RuleGroup>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ProcessTerminate onmatch=\"exclude\">\n\t\t</ProcessTerminate>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 6 : DRIVER LOADED INTO KERNEL [DriverLoad]-->\n\t\t<!--COMMENT:\tBecause drivers with bugs can be used to escalate to kernel permissions, be extremely selective\n\t\t\tabout what you exclude from monitoring. Low event volume, little incentive to exclude.\n\t\t\t[ https://attack.mitre.org/wiki/Technique/T1014 ] -->\n\t\t<!--TECHNICAL:\tSysmon will check the signing certificate revocation status of any driver you don't exclude.-->\n\n\t\t<!--DATA: UtcTime, ImageLoaded, Hashes, Signed, Signature, SignatureStatus-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<DriverLoad onmatch=\"exclude\">\n\t\t\t<Signature condition=\"contains\">microsoft</Signature> <!--Exclude signed Microsoft drivers-->\n\t\t\t<Signature condition=\"contains\">windows</Signature> <!--Exclude signed Microsoft drivers-->\n\t\t\t<Signature condition=\"begin with\">Intel </Signature> <!--Exclude signed Intel drivers-->\n\t\t</DriverLoad>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 7 : DLL (IMAGE) LOADED BY PROCESS [ImageLoad]-->\n\t\t<!--COMMENT:\tCan cause high system load, disabled by default.-->\n\t\t<!--COMMENT:\t[ https://attack.mitre.org/wiki/Technique/T1073 ] [ https://attack.mitre.org/wiki/Technique/T1038 ] [ https://attack.mitre.org/wiki/Technique/T1034 ] -->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, ImageLoaded, Hashes, Signed, Signature, SignatureStatus-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ImageLoad onmatch=\"include\">\n\t\t\t<!--NOTE: Using \"include\" with no rules means nothing in this section will be logged-->\n\t\t</ImageLoad>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 8 : REMOTE THREAD CREATED [CreateRemoteThread]-->\n\t\t<!--COMMENT:\tMonitor for processes injecting code into other processes. Often used by malware to cloak their actions. Also when Firefox loads Flash.\n\t\t[ https://attack.mitre.org/wiki/Technique/T1055 ] -->\n\n\t\t<!--DATA: UtcTime, SourceProcessGuid, SourceProcessId, SourceImage, TargetProcessId, TargetImage, NewThreadId, StartAddress, StartModule, StartFunction-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<CreateRemoteThread onmatch=\"exclude\">\n\t\t\t<!--COMMENT: Exclude mostly-safe sources and log anything else.-->\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\wbem\\WmiPrvSE.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\svchost.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\wininit.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\csrss.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\services.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\winlogon.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\audiodg.exe</SourceImage>\n\t\t\t<StartModule condition=\"is\">C:\\Windows\\system32\\kernel32.dll</StartModule>\n\t\t\t<TargetImage condition=\"is\">C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe</TargetImage>\n\t\t</CreateRemoteThread>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 9 : RAW DISK ACCESS [RawAccessRead]-->\n\t\t<!--EVENT 9: \"RawAccessRead detected\"-->\n\t\t<!--COMMENT:\tCan cause high system load, disabled by default.-->\n\t\t<!--COMMENT:\tMonitor for raw sector-level access to the disk, often used to bypass access control lists or access locked files.\n\t\t\tDisabled by default since including even one entry here activates this component. Reward/performance/rule maintenance decision.\n\t\t\tEncourage you to experiment with this feature yourself. [ https://attack.mitre.org/wiki/Technique/T1067 ] -->\n\t\t<!--COMMENT:\tYou will likely want to set this to a full capture on domain controllers, where no process should be doing raw reads.-->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, Device-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<RawAccessRead onmatch=\"include\">\n\t\t\t<!--NOTE: Using \"include\" with no rules means nothing in this section will be logged-->\n\t\t</RawAccessRead>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 10 : INTER-PROCESS ACCESS [ProcessAccess]-->\n\t\t<!--EVENT 10: \"Process accessed\"-->\n\t\t<!--COMMENT:\tCan cause high system load, disabled by default.-->\n\t\t<!--COMMENT:\tMonitor for processes accessing other process' memory.-->\n\n\t\t<!--DATA: UtcTime, SourceProcessGuid, SourceProcessId, SourceThreadId, SourceImage, TargetProcessGuid, TargetProcessId, TargetImage, GrantedAccess, CallTrace-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ProcessAccess onmatch=\"include\">\n\t\t\t<!--NOTE: Using \"include\" with no rules means nothing in this section will be logged-->\n\t\t</ProcessAccess>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 11 : FILE CREATED [FileCreate]-->\n\t\t<!--EVENT 11: \"File created\"-->\n\t\t<!--NOTE:\tOther filesystem \"minifilters\" can make it appear to Sysmon that some files are being written twice. This is not a Sysmon issue, per Mark Russinovich.-->\n\t\t<!--NOTE:\tYou may not see files detected by antivirus. Other filesystem minifilters, like antivirus, can act before Sysmon receives the alert a file was written.-->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, TargetFilename, CreationUtcTime-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<FileCreate onmatch=\"include\">\n\t\t\t<TargetFilename name=\"T1023\" condition=\"contains\">\\Start Menu</TargetFilename> <!--Windows: Startup links and shortcut modification [ https://attack.mitre.org/wiki/Technique/T1023 ] -->\n\t\t\t<TargetFilename name=\"T1165\" condition=\"contains\">\\Startup\\</TargetFilename> <!--Microsoft:Changes to user's auto-launched files and shortcuts-->\n\t\t\t<TargetFilename name=\"OutlookAttachment\" condition=\"contains\">\\Content.Outlook\\</TargetFilename> <!--Microsoft:Outlook: attachments-->\n\t\t\t<TargetFilename name=\"Downloads\" condition=\"contains\">\\Downloads\\</TargetFilename> <!--Downloaded files. Does not include \"Run\" files in IE-->\n\t\t\t<TargetFilename condition=\"end with\">.application</TargetFilename> <!--Microsoft:ClickOnce: [ https://blog.netspi.com/all-you-need-is-one-a-clickonce-love-story/ ] -->\n\t\t\t<TargetFilename condition=\"end with\">.appref-ms</TargetFilename> <!--Microsoft:ClickOnce application | Credit @ion-storm -->\n\t\t\t<TargetFilename condition=\"end with\">.bat</TargetFilename> <!--Batch scripting-->\n\t\t\t<TargetFilename condition=\"end with\">.chm</TargetFilename>\n\t\t\t<TargetFilename condition=\"end with\">.cmd</TargetFilename> <!--Batch scripting: Batch scripts can also use the .cmd extension | Credit: @mmazanec -->\n\t\t\t<TargetFilename condition=\"end with\">.cmdline</TargetFilename> <!--Microsoft:dotNet: Executed by cvtres.exe-->\n\t\t\t<TargetFilename name=\"T1176\" condition=\"end with\">.crx</TargetFilename> <!--Chrome extension-->\n\t\t\t<TargetFilename condition=\"end with\">.dmp</TargetFilename> <!--Process dumps [ (fr) http://blog.gentilkiwi.com/securite/mimikatz/minidump ] -->\n\t\t\t<TargetFilename condition=\"end with\">.docm</TargetFilename> <!--Microsoft:Office:Word: Macro-->\n\t\t\t<TargetFilename name=\"DLL\" condition=\"end with\">.dll</TargetFilename> <!--Microsoft:Office:Word: Macro-->\n\t\t\t<TargetFilename name=\"EXE\" condition=\"end with\">.exe</TargetFilename> <!--Executable-->\n\t\t\t<TargetFilename name=\"ProcessHostingdotNETCode\" condition=\"end with\">.exe.log</TargetFilename> <!-- [ https://github.com/bitsadmin/nopowershell ] | Credit: @SBousseaden [ https://twitter.com/SBousseaden/status/1137493597769687040 ]  -->\n\t\t\t<TargetFilename condition=\"end with\">.jar</TargetFilename> <!--Java applets-->\n\t\t\t<TargetFilename condition=\"end with\">.jnlp</TargetFilename> <!--Java applets-->\n\t\t\t<TargetFilename condition=\"end with\">.jse</TargetFilename> <!--Scripting [ Example: https://www.sophos.com/en-us/threat-center/threat-analyses/viruses-and-spyware/Mal~Phires-C/detailed-analysis.aspx ] -->\n\t\t\t<TargetFilename condition=\"end with\">.hta</TargetFilename> <!--Scripting-->\n\t\t\t<TargetFilename condition=\"end with\">.job</TargetFilename> <!--Scheduled task-->\n\t\t\t<TargetFilename condition=\"end with\">.pptm</TargetFilename> <!--Microsoft:Office:Word: Macro-->\n\t\t\t<TargetFilename condition=\"end with\">.ps1</TargetFilename> <!--PowerShell [ More information: http://www.hexacorn.com/blog/2014/08/27/beyond-good-ol-run-key-part-16/ ] -->\n\t\t\t<TargetFilename condition=\"end with\">.sys</TargetFilename> <!--System driver files-->\n\t\t\t<TargetFilename condition=\"end with\">.scr</TargetFilename> <!--System driver files-->\n\t\t\t<TargetFilename condition=\"end with\">.vbe</TargetFilename> <!--VisualBasicScripting-->\n\t\t\t<TargetFilename condition=\"end with\">.vbs</TargetFilename> <!--VisualBasicScripting-->\n\t\t\t<TargetFilename condition=\"end with\">.xlsm</TargetFilename> <!--Microsoft:Office:Word: Macro-->\n\t\t\t<TargetFilename condition=\"end with\">.ocx</TargetFilename> <!--Microsoft:ActiveX-->\n\t\t\t<TargetFilename condition=\"end with\">proj</TargetFilename><!--Microsoft:MSBuild:Script: [ https://twitter.com/subTee/status/885919612969394177 ] -->\n\t\t\t<TargetFilename condition=\"end with\">.sln</TargetFilename><!--Microsoft:MSBuild:Script: [ https://twitter.com/subTee/status/885919612969394177 ] -->\n\t\t\t<TargetFilename condition=\"end with\">.xls</TargetFilename><!--Microsoft [ https://medium.com/@threathuntingteam/msxsl-exe-and-wmic-exe-a-way-to-proxy-code-execution-8d524f642b75 ] -->\n\t\t\t<TargetFilename name=\"DefaultUserModified\" condition=\"begin with\">C:\\Users\\Default</TargetFilename> <!--Windows: Changes to default user profile-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\system32\\Drivers</TargetFilename> <!--Microsoft: Drivers dropped here-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\SysWOW64\\Drivers</TargetFilename> <!--Microsoft: Drivers dropped here-->\n\t\t\t<TargetFilename name=\"T1037,T1484\" condition=\"begin with\">C:\\Windows\\system32\\GroupPolicy\\Machine\\Scripts</TargetFilename> <!--Group policy [ More information: http://www.hexacorn.com/blog/2017/01/07/beyond-good-ol-run-key-part-52/ ] -->\n\t\t\t<TargetFilename name=\"T1037,T1484\" condition=\"begin with\">C:\\Windows\\system32\\GroupPolicy\\User\\Scripts</TargetFilename> <!--Group policy [ More information: http://www.hexacorn.com/blog/2017/01/07/beyond-good-ol-run-key-part-52/ ] -->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\system32\\Wbem</TargetFilename> <!--Microsoft:WMI: [ More information: http://2014.hackitoergosum.org/slides/day1_WMI_Shell_Andrei_Dumitrescu.pdf ] -->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\SysWOW64\\Wbem</TargetFilename> <!--Microsoft:WMI: [ More information: http://2014.hackitoergosum.org/slides/day1_WMI_Shell_Andrei_Dumitrescu.pdf ] -->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\system32\\WindowsPowerShell</TargetFilename> <!--Microsoft:Powershell: Look for modifications for persistence [ https://www.malwarearchaeology.com/cheat-sheets ] -->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\SysWOW64\\WindowsPowerShell</TargetFilename> <!--Microsoft:Powershell: Look for modifications for persistence [ https://www.malwarearchaeology.com/cheat-sheets ] -->\n\t\t\t<TargetFilename name=\"T1053\" condition=\"begin with\">C:\\Windows\\Tasks\\</TargetFilename> <!--Microsoft:ScheduledTasks [ https://attack.mitre.org/wiki/Technique/T1053 ] -->\n\t\t\t<TargetFilename name=\"T1053\" condition=\"begin with\">C:\\Windows\\system32\\Tasks</TargetFilename> <!--Microsoft:ScheduledTasks [ https://attack.mitre.org/wiki/Technique/T1053 ] -->\n\t\t\t<TargetFilename name=\"T1053\" condition=\"begin with\">C:\\Windows\\SysWOW64\\Tasks</TargetFilename> <!--Microsoft:ScheduledTasks [ https://attack.mitre.org/wiki/Technique/T1053 ] -->\n\t\t\t<Image condition=\"begin with\">\\Device\\HarddiskVolumeShadowCopy</Image> <!--Nothing should be executing from VSC | Credit: @SBousseaden [ https://twitter.com/SBousseaden/status/1133030955407630336 ] -->\n\t\t\t<!--Windows application compatibility-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\AppPatch\\Custom</TargetFilename> <!--Windows: Application compatibility shims [ https://www.fireeye.com/blog/threat-research/2017/05/fin7-shim-databases-persistence.html ] -->\n\t\t\t<TargetFilename condition=\"contains\">VirtualStore</TargetFilename> <!--Windows: UAC virtualization [ https://blogs.msdn.microsoft.com/oldnewthing/20150902-00/?p=91681 ] -->\n\t\t\t<!--Exploitable file names-->\n\t\t\t<TargetFilename condition=\"end with\">.xls</TargetFilename> <!--Legacy Office files are often used for attacks-->\n\t\t\t<TargetFilename condition=\"end with\">.ppt</TargetFilename> <!--Legacy Office files are often used for attacks-->\n\t\t\t<TargetFilename condition=\"end with\">.rtf</TargetFilename> <!--RTF files often 0day malware vectors when opened by Office-->\n\t\t</FileCreate>\n\t</RuleGroup>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<FileCreate onmatch=\"exclude\">\n\t\t\t<!--SECTION: Microsoft-->\n\t\t\t<Image condition=\"is\">C:\\Program Files (x86)\\EMET 5.5\\EMET_Service.exe</Image> <!--Microsoft:EMET: Writes to C:\\Windows\\AppPatch\\-->\n\t\t\t<!--SECTION: Microsoft:Office:Click2Run-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Common Files\\Microsoft Shared\\ClickToRun\\OfficeC2RClient.exe</Image> <!-- Microsoft:Office Click2Run-->\n\t\t\t<!--SECTION: Windows-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\smss.exe</Image> <!-- Windows: Session Manager SubSystem: Creates swapfile.sys,pagefile.sys,hiberfile.sys-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\CompatTelRunner.exe</Image> <!-- Windows: Windows 10 app, creates tons of cache files-->\n\t\t\t<Image condition=\"is\">\\\\?\\C:\\Windows\\system32\\wbem\\WMIADAP.EXE</Image> <!-- Windows: WMI Performance updates-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\mobsync.exe</Image> <!--Windows: Network file syncing-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\system32\\DriverStore\\Temp\\</TargetFilename> <!-- Windows: Temp files by DrvInst.exe-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\system32\\wbem\\Performance\\</TargetFilename> <!-- Windows: Created in wbem by WMIADAP.exe-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\Installer\\</TargetFilename> <!--Windows:Installer: Ignore MSI installer files caching-->\n\t\t\t<!--SECTION: Windows:Updates-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\$WINDOWS.~BT\\Sources\\</TargetFilename> <!-- Windows: Feature updates containing lots of .exe and .sys-->\n\t\t\t<Image condition=\"begin with\">C:\\Windows\\winsxs\\amd64_microsoft-windows</Image> <!-- Windows: Windows update-->\n\t\t</FileCreate>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 12 & 13 & 14 : REGISTRY MODIFICATION [RegistryEvent]-->\n\t\t<!--EVENT 12: \"Registry object added or deleted\"-->\n\t\t<!--EVENT 13: \"Registry value set\"-->\n\t\t<!--EVENT 14: \"Registry objected renamed\"-->\n\n\t\t<!--NOTE:\tWindows writes hundreds or thousands of registry keys a minute, so just because you're not changing things, doesn't mean these rules aren't being run.-->\n\t\t<!--NOTE:\tYou do not have to spend a lot of time worrying about performance, CPUs are fast, but it's something to consider. Every rule and condition type has a small cost.-->\n\t\t<!--NOTE:\t\"contains\" works by finding the first letter, then matching the second, etc, so the first letters should be as low-occurrence as possible.-->\n\t\t<!--NOTE:\t[ https://attack.mitre.org/wiki/Technique/T1112 ] -->\n\n\t\t<!--TECHNICAL:\tYou cannot filter on the \"Details\" attribute, due to performance issues when very large keys are written, and variety of data formats-->\n\t\t<!--TECHNICAL:\tPossible prefixes are HKLM, HKCR, and HKU-->\n\t\t<!--CRITICAL:\tSchema version 3.30 and higher change HKLM\\=\"\\REGISTRY\\MACHINE\\\" and HKU\\=\"\\REGISTRY\\USER\\\" and HKCR\\=\"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\\" and CurrentControlSet=\"ControlSet001\"-->\n\t\t<!--CRITICAL:\tDue to a bug, Sysmon versions BEFORE 7.01 may not properly log with the new prefix style for registry keys that was originally introduced in schema version 3.30-->\n\t\t<!--NOTE:\tBecause Sysmon runs as a service, it has no filtering ability for, or concept of, HKCU or HKEY_CURRENT_USER. Use \"contains\" or \"end with\" to get around this limitation-->\n\n\t\t<!-- ! CRITICAL NOTE !:\tIt may appear this section is MISSING important entries, but SOME RULES MONITOR MANY KEYS, so look VERY CAREFULLY to see if something is already covered.\n\t\t\t\t\t\t\t\tSysmon's wildcard monitoring along with highly-tuned generic strings cuts the rulesets down immensely, compared to doing this in other tools.\n\t\t\t\t\t\t\t\tFor example, most COM hijacking in CLSID's across the registry is covered by a single rule monitoring a InProcServer32 wildcard-->\n\n\t\t<!--DATA: EventType, UtcTime, ProcessGuid, ProcessId, Image, TargetObject, Details (can't filter on), NewName (can't filter on)-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<RegistryEvent onmatch=\"include\">\n\t\t\t<!--Autorun or Startups-->\n\t\t\t\t<!--ADDITIONAL REFERENCE: [ http://www.ghacks.net/2016/06/04/windows-automatic-startup-locations/ ] -->\n\t\t\t\t<!--ADDITIONAL REFERENCE: [ https://view.officeapps.live.com/op/view.aspx?src=https://arsenalrecon.com/downloads/resources/Registry_Keys_Related_to_Autorun.ods ] -->\n\t\t\t\t<!--ADDITIONAL REFERENCE: [ http://www.silentrunners.org/launchpoints.html ] -->\n\t\t\t\t<!--ADDITIONAL REFERENCE: [ https://www.microsoftpressstore.com/articles/article.aspx?p=2762082&seqNum=2 ] -->\n\t\t\t\t<!--ADDITIONAL REFERENCE: [ https://web.archive.org/web/20200116001643/http://scholarworks.rit.edu/cgi/viewcontent.cgi?article=1533&context=theses | Understanding malware autostart techniques - Matthew Gottlieb ] -->\n\t\t\t<TargetObject name=\"T1060,RunKey\" condition=\"contains\">CurrentVersion\\Run</TargetObject> <!--Windows: Wildcard for Run keys, including RunOnce, RunOnceEx, RunServices, RunServicesOnce [Also covers terminal server] -->\n\t\t\t<TargetObject name=\"T1060,RunPolicy\" condition=\"contains\">Policies\\Explorer\\Run</TargetObject> <!--Windows: Alternate runs keys | Credit @ion-storm-->\n\t\t\t<TargetObject name=\"T1484\" condition=\"contains\">Group Policy\\Scripts</TargetObject> <!--Windows: Group policy scripts-->\n\t\t\t<TargetObject name=\"T1484\" condition=\"contains\">Windows\\System\\Scripts</TargetObject> <!--Windows: Wildcard for Logon, Loggoff, Shutdown-->\n\t\t\t<TargetObject name=\"T1060\" condition=\"contains\">CurrentVersion\\Windows\\Load</TargetObject> <!--Windows: [ https://msdn.microsoft.com/en-us/library/jj874148.aspx ] -->\n\t\t\t<TargetObject name=\"T1060\" condition=\"contains\">CurrentVersion\\Windows\\Run</TargetObject> <!--Windows: [ https://msdn.microsoft.com/en-us/library/jj874148.aspx ] -->\n\t\t\t<TargetObject name=\"T1060\" condition=\"contains\">CurrentVersion\\Winlogon\\Shell</TargetObject> <!--Windows: [ https://msdn.microsoft.com/en-us/library/ms838576(v=winembedded.5).aspx ] -->\n\t\t\t<TargetObject name=\"T1060\" condition=\"contains\">CurrentVersion\\Winlogon\\System</TargetObject> <!--Windows [ https://www.exterminate-it.com/malpedia/regvals/zlob-dns-changer/118 ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify</TargetObject> <!--Windows: Autorun location [ https://attack.mitre.org/wiki/Technique/T1004 ] [ https://www.cylance.com/windows-registry-persistence-part-2-the-run-keys-and-search-order ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Shell</TargetObject> <!--Windows: [ https://technet.microsoft.com/en-us/library/ee851671.aspx ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Userinit</TargetObject> <!--Windows: Autorun location [ https://www.cylance.com/windows-registry-persistence-part-2-the-run-keys-and-search-order ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\WOW6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32</TargetObject> <!--Windows: Legacy driver loading | Credit @ion-storm -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\BootExecute</TargetObject> <!--Windows: Autorun | Credit @ion-storm | [ https://www.cylance.com/windows-registry-persistence-part-2-the-run-keys-and-search-order ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug</TargetObject> <!--Windows: Automatic program crash debug program [ https://www.symantec.com/security_response/writeup.jsp?docid=2007-050712-5453-99&tabid=2 ] -->\n\t\t\t<TargetObject condition=\"contains\">UserInitMprLogonScript</TargetObject> <!--Windows: Legacy logon script environment variable [ http://www.hexacorn.com/blog/2014/11/14/beyond-good-ol-run-key-part-18/ ] -->\n\t\t\t<TargetObject name=\"T1112,ChangeStartupFolderPath\" condition=\"end with\">user shell folders\\startup</TargetObject> <!--Monitor changes to Startup folder location for monitoring evasion | Credit @SBousseaden-->\n\t\t\t<!--Services-->\n\t\t\t<TargetObject name=\"T1031,T1050\" condition=\"end with\">\\ServiceDll</TargetObject> <!--Windows: Points to a service's DLL [ https://blog.cylance.com/windows-registry-persistence-part-1-introduction-attack-phases-and-windows-services ] -->\n\t\t\t<TargetObject name=\"T1031,T1050\" condition=\"end with\">\\ServiceManifest</TargetObject> <!--Windows: Manifest pointing to service's DLL [ https://www.geoffchappell.com/studies/windows/win32/services/svchost/index.htm ] -->\n\t\t\t<TargetObject name=\"T1031,T1050\" condition=\"end with\">\\ImagePath</TargetObject> <!--Windows: Points to a service's EXE [ https://attack.mitre.org/wiki/Technique/T1050 ] -->\n\t\t\t<TargetObject name=\"T1031,T1050\" condition=\"end with\">\\Start</TargetObject> <!--Windows: Services start mode changes (Disabled, Automatically, Manual)-->\n\t\t\t<!--RDP-->\n\t\t\t<TargetObject name=\"RDP port change\" condition=\"end with\">Control\\Terminal Server\\WinStations\\RDP-Tcp\\PortNumber</TargetObject> <!--Windows: RDP port change under Control [ https://blog.menasec.net/2019/02/of-rdp-hijacking-part1-remote-desktop.html ]-->\n\t\t\t<TargetObject name=\"RDP port change\" condition=\"end with\">Control\\Terminal Server\\fSingleSessionPerUser</TargetObject> <!--Windows: Allow same user to have mutliple RDP sessions, to hide from admin being impersonated-->\n\t\t\t<TargetObject name=\"ModifyRemoteDesktopState\" condition=\"end with\">fDenyTSConnections</TargetObject> <!--Windows: Attacker turning on RDP-->\n\t\t\t<TargetObject condition=\"end with\">LastLoggedOnUser</TargetObject> <!--Windows: Changing last-logged in user-->\n\t\t\t<TargetObject name=\"ModifyRemoteDesktopPort\" condition=\"end with\">RDP-tcp\\PortNumber</TargetObject> <!--Windows: Changing RDP port to evade IDS-->\n\t\t\t<TargetObject condition=\"end with\">Services\\PortProxy\\v4tov4</TargetObject> <!--Windows: Changing RDP port to evade IDS-->\n\t\t\t<!--CLSID launch commands and Default File Association changes-->\n\t\t\t<TargetObject name=\"T1042\" condition=\"contains\">\\command\\</TargetObject> <!--Windows: Sensitive sub-key under file associations and CLSID that map to launch command-->\n\t\t\t<TargetObject name=\"T1122\" condition=\"contains\">\\ddeexec\\</TargetObject> <!--Windows: Sensitive sub-key under file associations and CLSID that map to launch command-->\n\t\t\t<TargetObject name=\"T1122\" condition=\"contains\">{86C86720-42A0-1069-A2E8-08002B30309D}</TargetObject> <!--Windows: Tooltip handler-->\n\t\t\t<TargetObject name=\"T1042\" condition=\"contains\">exefile</TargetObject> <!--Windows Executable handler, to log any changes not already monitored-->\n\t\t\t<!--Windows COM-->\n\t\t\t<TargetObject name=\"T1122\" condition=\"end with\">\\InprocServer32\\(Default)</TargetObject> <!--Windows:COM Object Hijacking [ https://blog.gdatasoftware.com/2014/10/23941-com-object-hijacking-the-discreet-way-of-persistence ] | Credit @ion-storm -->\n\t\t\t<!--Windows shell visual modifications used by malware-->\n\t\t\t<TargetObject name=\"T1158\" condition=\"end with\">\\Hidden</TargetObject> <!--Windows:Explorer: Some types of malware try to hide their hidden system files from the user, good signal event -->\n\t\t\t<TargetObject name=\"T1158\" condition=\"end with\">\\ShowSuperHidden</TargetObject> <!--Windows:Explorer: Some types of malware try to hide their hidden system files from the user, good signal event [ Example: https://www.symantec.com/security_response/writeup.jsp?docid=2007-061811-4341-99&tabid=2 ] -->\n\t\t\t<TargetObject name=\"T1158\" condition=\"end with\">\\HideFileExt</TargetObject> <!--Windows:Explorer: Some malware hides file extensions to make diagnosis/disinfection more daunting to novice users -->\n\t\t\t<!--Windows shell hijack and modifications-->\n\t\t\t<TargetObject condition=\"contains\">Classes\\*\\</TargetObject> <!--Windows:Explorer: [ http://www.silentrunners.org/launchpoints.html ] -->\n\t\t\t<TargetObject condition=\"contains\">Classes\\AllFilesystemObjects\\</TargetObject> <!--Windows:Explorer: [ http://www.silentrunners.org/launchpoints.html ] -->\n\t\t\t<TargetObject condition=\"contains\">Classes\\Directory\\</TargetObject> <!--Windows:Explorer: [ https://stackoverflow.com/questions/1323663/windows-shell-context-menu-option ] -->\n\t\t\t<TargetObject condition=\"contains\">Classes\\Drive\\</TargetObject> <!--Windows:Explorer: [ https://stackoverflow.com/questions/1323663/windows-shell-context-menu-option ] -->\n\t\t\t<TargetObject condition=\"contains\">Classes\\Folder\\</TargetObject> <!--Windows:Explorer: ContextMenuHandlers, DragDropHandlers, CopyHookHandlers, [ https://stackoverflow.com/questions/1323663/windows-shell-context-menu-option ] -->\n\t\t\t<TargetObject condition=\"contains\">Classes\\PROTOCOLS\\</TargetObject> <!--Windows:Explorer: Protocol handlers-->\n\t\t\t<TargetObject condition=\"contains\">ContextMenuHandlers\\</TargetObject> <!--Windows: [ http://oalabs.openanalysis.net/2015/06/04/malware-persistence-hkey_current_user-shell-extension-handlers/ ] -->\n\t\t\t<TargetObject condition=\"contains\">CurrentVersion\\Shell</TargetObject> <!--Windows: Shell Folders, ShellExecuteHooks, ShellIconOverloadIdentifers, ShellServiceObjects, ShellServiceObjectDelayLoad [ http://oalabs.openanalysis.net/2015/06/04/malware-persistence-hkey_current_user-shell-extension-handlers/ ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\explorer\\ShellExecuteHooks</TargetObject> <!--Windows: ShellExecuteHooks-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\explorer\\ShellServiceObjectDelayLoad</TargetObject> <!--Windows: ShellExecuteHooks-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\explorer\\ShellIconOverlayIdentifiers</TargetObject> <!--Windows: ShellExecuteHooks-->\n\t\t\t<!--AppPaths hijacking-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\</TargetObject> <!--Windows: Credit to @Hexacorn [ http://www.hexacorn.com/blog/2013/01/19/beyond-good-ol-run-key-part-3/ ] -->\n\t\t\t<!--Terminal service boobytrap-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp\\InitialProgram</TargetObject> <!--Windows:RDP: Note other Terminal Server run keys are handled by another wildcard already-->\n\t\t\t<!--Group Policy integrity-->\n\t\t\t<TargetObject name=\"T1484\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPExtensions\\</TargetObject> <!--Windows: Group Policy internally uses a plug-in architecture that nothing should be modifying-->\n\t\t\t<!--Winsock and Winsock2-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Services\\WinSock</TargetObject> <!--Windows: Wildcard, includes Winsock and Winsock2-->\n\t\t\t<TargetObject condition=\"end with\">\\ProxyServer</TargetObject> <!--Windows: System and user proxy server-->\n\t\t\t<!--Credential providers-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Authentication\\Credential Provider</TargetObject> <!--Wildcard, includes Credential Providers and Credential Provider Filters-->\n\t\t\t<TargetObject name=\"T1101\" condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\</TargetObject> <!-- [ https://attack.mitre.org/wiki/Technique/T1131 ] [ https://attack.mitre.org/wiki/Technique/T1101 ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SecurityProviders</TargetObject> <!--Windows: Changes to WDigest-UseLogonCredential for password scraping [ https://www.trustedsec.com/april-2015/dumping-wdigest-creds-with-meterpreter-mimikatzkiwi-in-windows-8-1/ ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Netsh</TargetObject> <!--Windows: Netsh helper DLL [ https://attack.mitre.org/wiki/Technique/T1128 ] -->\n\t\t\t<TargetObject condition=\"contains\">Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ProxyEnable</TargetObject> <!--Windows: Malware often disables a web proxy for 2nd stage downloads -->\n\t\t\t<!--Networking-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order\\</TargetObject> <!--Windows: Order of network providers that are checked to connect to destination [ https://www.malwarearchaeology.com/cheat-sheets ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles</TargetObject> <!--Windows: | Credit @ion-storm -->\n\t\t\t<TargetObject name=\"T1089\" condition=\"end with\">\\EnableFirewall</TargetObject> <!--Windows: Monitor for firewall disablement, all firewall profiles [ https://attack.mitre.org/wiki/Technique/T1089 ] -->\n\t\t\t<TargetObject name=\"T1089\" condition=\"end with\">\\DoNotAllowExceptions</TargetObject> <!--Windows: Monitor for firewall disablement, all firewall profiles [ https://attack.mitre.org/wiki/Technique/T1089 ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\StandardProfile\\AuthorizedApplications\\List</TargetObject> <!--Windows Firewall authorized applications for all networks| Credit @ion-storm -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\DomainProfile\\AuthorizedApplications\\List</TargetObject> <!--Windows Firewall authorized applications for domain networks -->\n\t\t\t<!--DLLs that get injected into every process at launch-->\n\t\t\t<TargetObject name=\"T1103\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows\\Appinit_Dlls\\</TargetObject> <!--Windows: Feature disabled by default [ https://attack.mitre.org/wiki/Technique/T1103 ] -->\n\t\t\t<TargetObject name=\"T1103\" condition=\"begin with\">HKLM\\Software\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows\\Appinit_Dlls\\</TargetObject> <!--Windows: Feature disabled by default [ https://attack.mitre.org/wiki/Technique/T1103 ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCertDlls\\</TargetObject> <!--Windows: Credit to @Hexacorn [ http://www.hexacorn.com/blog/2013/01/19/beyond-good-ol-run-key-part-3/ ] [ https://blog.comodo.com/malware/trojware-win32-trojanspy-volisk-a/ ] -->\n\t\t\t<!--Office-->\n\t\t\t<TargetObject name=\"T1137\" condition=\"contains\">Microsoft\\Office\\Outlook\\Addins\\</TargetObject> <!--Microsoft:Office: Outlook add-ins, access to sensitive data and often cause issues-->\n\t\t\t<TargetObject name=\"T1137\" condition=\"contains\">Office Test\\</TargetObject> <!-- Microsoft:Office: Persistence method [ http://www.hexacorn.com/blog/2014/04/16/beyond-good-ol-run-key-part-10/ ] | Credit @Hexacorn -->\n\t\t\t<TargetObject name=\"Context,ProtectedModeExitOrMacrosUsed\" condition=\"contains\">Security\\Trusted Documents\\TrustRecords</TargetObject> <!--Microsoft:Office: Monitor when \"Enable editing\" or \"Enable macros\" is used | Credit @OutflankNL | [ https://outflank.nl/blog/2018/01/16/hunting-for-evil-detect-macros-being-executed/ ] -->\n\t\t\t<TargetObject name=\"Context,ContactedDomain\" condition=\"end with\">\\EnableBHO</TargetObject> <!--Microsoft:Office: Contacted domains stored here 'HKEY_CURRENT_USER\\<SID>\\SOFTWARE\\Microsoft\\Office\\16.0\\Common\\Internet\\Server Cache\\<domain>\\EnableBHO' -->\n\t\t\t<!--IE-->\n\t\t\t<TargetObject name=\"T1176\" condition=\"contains\">Internet Explorer\\Toolbar\\</TargetObject> <!--Microsoft:InternetExplorer: Machine and user [ Example: https://www.exterminate-it.com/malpedia/remove-mywebsearch ] -->\n\t\t\t<TargetObject name=\"T1176\" condition=\"contains\">Internet Explorer\\Extensions\\</TargetObject> <!--Microsoft:InternetExplorer: Machine and user [ Example: https://www.exterminate-it.com/malpedia/remove-mywebsearch ] -->\n\t\t\t<TargetObject name=\"T1176\" condition=\"contains\">Browser Helper Objects\\</TargetObject> <!--Microsoft:InternetExplorer: Machine and user [ https://msdn.microsoft.com/en-us/library/bb250436(v=vs.85).aspx ] -->\n\t\t\t<TargetObject condition=\"end with\">\\DisableSecuritySettingsCheck</TargetObject>\n\t\t\t<TargetObject condition=\"end with\">\\3\\1206</TargetObject> <!--Microsoft:InternetExplorer: Malware sometimes assures scripting is on in Internet Zone [ https://support.microsoft.com/en-us/help/182569/internet-explorer-security-zones-registry-entries-for-advanced-users ] -->\n\t\t\t<TargetObject condition=\"end with\">\\3\\2500</TargetObject> <!--Microsoft:InternetExplorer: Malware sometimes disables Protected Mode in Internet Zone [ https://blog.avast.com/2013/08/12/your-documents-are-corrupted-from-image-to-an-information-stealing-trojan/ ] -->\n\t\t\t<TargetObject condition=\"end with\">\\3\\1809</TargetObject> <!--Microsoft:InternetExplorer: Malware sometimes disables Pop-up Blocker in Internet Zone [ https://support.microsoft.com/en-us/help/182569/internet-explorer-security-zones-registry-entries-for-advanced-users ] -->\n\t\t\t<!--Magic registry keys-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Classes\\CLSID\\{AB8902B4-09CA-4BB6-B78D-A8F59079A8D5}\\</TargetObject> <!--Windows: Thumbnail cache autostart [ http://blog.trendmicro.com/trendlabs-security-intelligence/poweliks-levels-up-with-new-autostart-mechanism/ ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Classes\\WOW6432Node\\CLSID\\{AB8902B4-09CA-4BB6-B78D-A8F59079A8D5}\\</TargetObject> <!--Windows: Thumbnail cache autostart [ http://blog.trendmicro.com/trendlabs-security-intelligence/poweliks-levels-up-with-new-autostart-mechanism/ ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Classes\\CLSID\\{083863F1-70DE-11d0-BD40-00A0C911CE86}\\</TargetObject> <!--Windows: DirectX instances-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Classes\\WOW6432Node\\CLSID\\{083863F1-70DE-11d0-BD40-00A0C911CE86}\\</TargetObject> <!--Windows: DirectX instances-->\n\t\t\t<!--Install/Run artifacts-->\n\t\t\t<TargetObject condition=\"end with\">\\UrlUpdateInfo</TargetObject> <!--Microsoft:ClickOnce: Source URL is stored in this value [ https://subt0x10.blogspot.com/2016/12/mimikatz-delivery-via-clickonce-with.html ] -->\n\t\t\t<TargetObject condition=\"end with\">\\InstallSource</TargetObject> <!--Windows: Source folder for certain program and component installations-->\n\t\t\t<TargetObject name=\"Alert,Sysinternals Tool Used\" condition=\"end with\">\\EulaAccepted</TargetObject> <!--Sysinternals tool launched. Lots of useful abilities for attackers -->\n\t\t\t<!--Antivirus tampering-->\n\t\t\t<TargetObject name=\"T1089,Tamper-Defender\" condition=\"end with\">\\DisableAntiSpyware</TargetObject> <!--Windows:Defender: State modified via registry-->\n\t\t\t<TargetObject name=\"T1089,Tamper-Defender\" condition=\"end with\">\\DisableAntiVirus</TargetObject> <!--Windows:Defender: State modified via registry-->\n\t\t\t<TargetObject name=\"T1089,Tamper-Defender\" condition=\"end with\">\\SpynetReporting</TargetObject> <!--Windows:Defender: State modified via registry-->\n\t\t\t<TargetObject name=\"T1089,Tamper-Defender\" condition=\"end with\">DisableRealtimeMonitoring</TargetObject> <!--Windows:Defender: State modified via registry-->\n\t\t\t<TargetObject name=\"T1089,Tamper-Defender\" condition=\"end with\">\\SubmitSamplesConsent</TargetObject> <!--Windows:Defender: State modified via registry-->\n\t\t\t<!--Windows UAC tampering-->\n\t\t\t<TargetObject name=\"T1088\" condition=\"end with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\EnableLUA</TargetObject> <!--Detect: UAC Tampering | Credit @ion-storm -->\n\t\t\t<TargetObject name=\"T1088\" condition=\"end with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\LocalAccountTokenFilterPolicy</TargetObject> <!--Detect: UAC Tampering | Credit @ion-storm -->\n\t\t\t<!--Microsoft Security Center tampering | Credit @ion-storm -->\n\t\t\t<TargetObject name=\"T1089,Tamper-SecCenter\" condition=\"end with\">HKLM\\Software\\Microsoft\\Security Center\\</TargetObject> <!-- [ https://attack.mitre.org/wiki/Technique/T1089 ] -->\n\t\t\t<TargetObject name=\"T1089,Tamper-SecCenter\" condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\HideSCAHealth</TargetObject> <!--Windows:Security Center: Malware sometimes disables [ https://blog.avast.com/2013/08/12/your-documents-are-corrupted-from-image-to-an-information-stealing-trojan/ ] -->\n\t\t\t<!--Windows application compatibility-->\n\t\t\t<TargetObject name=\"T1138,AppCompatShim\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Custom</TargetObject> <!--Windows: AppCompat [ https://www.fireeye.com/blog/threat-research/2017/05/fin7-shim-databases-persistence.html ] -->\n\t\t\t<TargetObject name=\"T1138,AppCompatShim\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\InstalledSDB</TargetObject> <!--Windows: AppCompat [ https://attack.mitre.org/wiki/Technique/T1138 ] -->\n\t\t\t<TargetObject condition=\"contains\">VirtualStore</TargetObject> <!--Windows: Registry virtualization, something's wrong if it's in use [ https://msdn.microsoft.com/en-us/library/windows/desktop/aa965884(v=vs.85).aspx ] -->\n\t\t\t<!--Windows internals integrity monitoring-->\n\t\t\t<TargetObject name=\"T1183,IFEO\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\</TargetObject> <!--Windows: Malware likes changing IFEO, like adding Debugger to disable antivirus EXE-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\</TargetObject> <!--Windows: Event log system integrity and ACLs-->\n\t\t\t<TargetObject name=\"Tamper-Safemode\" condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Safeboot\\</TargetObject> <!--Windows: Services approved to load in safe mode. Almost nothing should ever modify this.-->\n\t\t\t<TargetObject name=\"Tamper-Winlogon\" condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Winlogon\\</TargetObject> <!--Windows: Providers notified by WinLogon-->\n\t\t\t<TargetObject name=\"Context,DeviceConnectedOrUpdated\" condition=\"end with\">\\FriendlyName</TargetObject> <!--Windows: New devices connected and remembered-->\n\t\t\t<TargetObject name=\"Context,MsiInstallerStarted\" condition=\"is\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\InProgress\\(Default)</TargetObject> <!--Windows: See when WindowsInstaller is engaged, useful for timeline matching with other events-->\n\t\t\t<TargetObject name=\"Tamper-Tracing\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Tracing\\RASAPI32</TargetObject> <!--Windows: Malware sometimes disables tracing to obfuscate tracks-->\n\t\t\t<TargetObject name=\"Context,ProcessAccessedPrivateResource\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\CapabilityAccessManager\\ConsentStore\\</TargetObject> <!-- Windows: Win10 tracks when and what process uses webcam/microphone/location etc [ https://medium.com/@7a616368/can-you-track-processes-accessing-the-camera-and-microphone-7e6885b37072 ] -->\n\t\t\t<!--Windows inventory events-->\n\t\t\t<TargetObject name=\"InvDB-Path\" condition=\"end with\">\\LowerCaseLongPath</TargetObject> <!-- [ https://binaryforay.blogspot.com/2017/10/amcache-still-rules-everything-around.html ] -->\n\t\t\t<TargetObject name=\"InvDB-Pub\" condition=\"end with\">\\Publisher</TargetObject> <!-- [ https://binaryforay.blogspot.com/2017/10/amcache-still-rules-everything-around.html ] -->\n\t\t\t<TargetObject name=\"InvDB-Ver\" condition=\"end with\">\\BinProductVersion</TargetObject> <!-- [ https://docs.microsoft.com/en-us/windows/privacy/basic-level-windows-diagnostic-events-and-fields-1709 ] -->\n\t\t\t<TargetObject name=\"InvDB-DriverVer\" condition=\"end with\">\\DriverVersion</TargetObject> <!-- [ https://df-stream.com/2015/02/leveraging-devicecontainers-key/ ] -->\n\t\t\t<TargetObject name=\"InvDB-DriverVer\" condition=\"end with\">\\DriverVerVersion</TargetObject> <!-- [ https://df-stream.com/2015/02/leveraging-devicecontainers-key/ ] -->\n\t\t\t<TargetObject name=\"InvDB-CompileTimeClaim\" condition=\"end with\">\\LinkDate</TargetObject> <!-- Compile time of EXE, may not be reliable [ https://en.wikipedia.org/wiki/Link_time ] -->\n\t\t\t<TargetObject name=\"InvDB\" condition=\"contains\">Compatibility Assistant\\Store\\</TargetObject> <!-- Inventory -->\n\t\t\t<!--Suspicious sources-->\n\t\t\t<Image name=\"Suspicious,ImageBeginWithBackslash\" condition=\"end with\">regedit.exe</Image> <!--Users and helpdesk staff making system modifications -->\n\t\t\t<Image name=\"Suspicious,ImageBeginWithBackslash\" condition=\"begin with\">\\</Image> <!--Devices and VSC shouldn't be executing changes | Credit: @SBousseaden @ionstorm @neu5ron @PerchedSystems [ https://twitter.com/SwiftOnSecurity/status/1133167323991486464 ] -->\n\t\t</RegistryEvent>\n\t</RuleGroup>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<RegistryEvent onmatch=\"exclude\">\n\t\t<!--COMMENT:\tRemove low-information noise. Often these hide a procress recreating an empty key and do not hide the values created subsequently.-->\n\t\t<!--NOTE:\tA lot of noise can be removed by excluding CreateKey events, which are largely innocuous-->\n\t\t\t<TargetObject condition=\"contains\">\\{CAFEEFAC-</TargetObject>\n\t\t\t<EventType condition=\"is\">CreateKey</EventType>\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\COMPONENTS</TargetObject>\n\t\t\t<!--Inventory noise-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\AppModel\\StateRepository\\Cache</TargetObject>\n\t\t\t<!--Misc-->\n\t\t\t<TargetObject condition=\"end with\">Toolbar\\WebBrowser</TargetObject> <!--Microsoft:IE: Extraneous activity-->\n\t\t\t<TargetObject condition=\"end with\">Browser\\ITBar7Height</TargetObject> <!--Microsoft:IE: Extraneous activity, covers ShellBrowser and WebBrowser-->\n\t\t\t<TargetObject condition=\"end with\">Browser\\ITBar7Layout</TargetObject> <!--Microsoft:IE: Extraneous activity-->\n\t\t\t<TargetObject condition=\"end with\">Internet Explorer\\Toolbar\\Locked</TargetObject> <!--Windows:Explorer: Extraneous activity-->\n\t\t\t<TargetObject condition=\"end with\">Toolbar\\WebBrowser\\{47833539-D0C5-4125-9FA8-0819E2EAAC93}</TargetObject> <!--Windows:Explorer: Extraneous activity-->\n\t\t\t<TargetObject condition=\"end with\">}\\PreviousPolicyAreas</TargetObject> <!--Windows: Remove noise from \\Winlogon\\GPExtensions by svchost.exe-->\n\t\t\t<TargetObject condition=\"contains\">\\Control\\WMI\\Autologger\\</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">HKLM\\SYSTEM\\CurrentControlSet\\Services\\UsoSvc\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">\\Lsa\\OfflineJoin\\CurrentValue</TargetObject> <!--Windows: Sensitive value during domain join-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\</TargetObject> <!--Windows: Remove noise monitoring installations run as system-->\n\t\t\t<TargetObject condition=\"contains\">_Classes\\AppX</TargetObject> <!--Windows: Remove noise monitoring \"Shell\\open\\command\"--> <!--Win8+-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\</TargetObject> <!--Windows: SvcHost Noise-->\n\t\t\t<!--Bootup Control noise-->\n\t\t\t<TargetObject condition=\"end with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\LsaPid</TargetObject> <!--Windows:lsass.exe: Boot noise-->\n\t\t\t<TargetObject condition=\"end with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\SspiCache</TargetObject> <!--Windows:lsass.exe: Boot noise--> <!--Win8+-->\n\t\t\t<TargetObject condition=\"end with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\Kerberos\\Domains</TargetObject> <!--Windows:lsass.exe: Boot noise--> <!--Win8+-->\n\t\t\t<!--Services startup settings noise, some low-risk services routinely change it and this can be ignored-->\n\t\t\t<TargetObject condition=\"end with\">\\Services\\BITS\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\clr_optimization_v2.0.50727_32\\Start</TargetObject> <!--Microsoft:dotNet: Windows 7-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\clr_optimization_v2.0.50727_64\\Start</TargetObject> <!--Microsoft:dotNet: Windows 7-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\clr_optimization_v4.0.30319_32\\Start</TargetObject> <!--Microsoft:dotNet: Windows 10-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\clr_optimization_v4.0.30319_64\\Start</TargetObject> <!--Microsoft:dotNet: Windows 10-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\deviceAssociationService\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\fhsvc\\Start</TargetObject> <!--Windows: File History Service-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\nal\\Start</TargetObject> <!--Intel: Network adapter diagnostic driver-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\trustedInstaller\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\tunnel\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\usoSvc\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<!--FileExts noise filtering-->\n\t\t\t<TargetObject condition=\"end with\">\\UserChoice\\ProgId</TargetObject> <!--Windows: Remove noise from monitoring \"FileExts\"--> <!--Win8+-->\n\t\t\t<TargetObject condition=\"end with\">\\UserChoice\\Hash</TargetObject> <!--Windows: Remove noise from monitoring \"FileExts\"--> <!--Win8+-->\n\t\t\t<TargetObject condition=\"end with\">\\OpenWithList\\MRUList</TargetObject> <!--Windows: Remove noise from monitoring \"FileExts\"-->\n\t\t\t<TargetObject condition=\"contains\">Shell Extentions\\Cached</TargetObject> <!--Windows: Remove noise generated by explorer.exe on monitored ShellCached binary keys--> <!--Win8+-->\n\t\t\t<!--Group Policy noise-->\n\t\t\t<TargetObject condition=\"end with\">HKLM\\System\\CurrentControlSet\\Control\\Lsa\\Audit\\SpecialGroups</TargetObject> <!--Windows: Routinely set through Group Policy, not especially important to log-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Startup\\0\\PSScriptOrder</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Startup\\0\\SOM-ID</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Startup\\0\\GPO-ID</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Startup\\0\\0\\IsPowershell</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Startup\\0\\0\\ExecTime</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Shutdown\\0\\PSScriptOrder</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Shutdown\\0\\SOM-ID</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Shutdown\\0\\GPO-ID</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Shutdown\\0\\0\\IsPowershell</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Shutdown\\0\\0\\ExecTime</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"contains\">\\safer\\codeidentifiers\\0\\HASHES\\{</TargetObject> <!--Windows: Software Restriction Policies. Can be used to disable security tools, but very noisy to monitor if you use it-->\n\t\t\t<!--SECTION: Office C2R-->\n\t\t\t<TargetObject condition=\"contains\">VirtualStore\\MACHINE\\SOFTWARE\\Microsoft\\Office\\ClickToRun\\</TargetObject> <!--Microsoft: SearchProtocolHost writes to OfficeC2R registry for Outlook, seemingly regarding mail indexing-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SOFTWARE\\Microsoft\\Office\\ClickToRun\\</TargetObject> <!--Microsoft: Virtual registry for Office-->\n\t\t\t<!--SECTION: 3rd party-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\WIDCOMM\\Bluetooth Software\\btwdins.exe</Image> <!--Constantly writes to HKLM-->\n\t\t\t<TargetObject condition=\"begin with\">HKCR\\VLC.</TargetObject> <!--VLC update noise-->\n\t\t\t<TargetObject condition=\"begin with\">HKCR\\iTunes.</TargetObject> <!--Apple: iTunes update noise-->\n\t\t\t<!--WINEVT publishers noise-->\n\t\t\t<TargetObject condition=\"is\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\{945a8954-c147-4acd-923f-40c45405a658}</TargetObject> <!--Windows update-->\n\t\t</RegistryEvent>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 15 : ALTERNATE DATA STREAM CREATED [FileCreateStreamHash]-->\n\t\t<!--EVENT 15: \"File stream created\"-->\n\t\t<!--COMMENT:\tAny files created with an NTFS Alternate Data Stream which match these rules will be hashed and logged.\n\t\t\t[ https://blogs.technet.microsoft.com/askcore/2013/03/24/alternate-data-streams-in-ntfs/ ]\n\t\t\tADS's are used by browsers and email clients to mark files as originating from the Internet or other foreign sources.\n\t\t\t[ https://textslashplain.com/2016/04/04/downloads-and-the-mark-of-the-web/ ] -->\n\t\t<!--NOTE: Other filesystem minifilters can make it appear to Sysmon that some files are being written twice. This is not a Sysmon issue, per Mark Russinovich.-->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, TargetFilename, CreationUtcTime, Hash-->\n\t\t<FileCreateStreamHash onmatch=\"include\">\n\t\t\t<TargetFilename condition=\"contains\">Downloads</TargetFilename> <!--Downloaded files. Does not include \"Run\" files in IE-->\n\t\t\t<TargetFilename condition=\"contains\">Temp\\7z</TargetFilename> <!--7zip extractions-->\n\t\t\t<TargetFilename condition=\"contains\">Startup</TargetFilename> <!--ADS startup | Example: [ https://www.hybrid-analysis.com/sample/a314f6106633fba4b70f9d6ddbee452e8f8f44a72117749c21243dc93c7ed3ac?environmentId=100 ] -->\n\t\t\t<TargetFilename condition=\"end with\">.bat</TargetFilename> <!--Batch scripting-->\n\t\t\t<TargetFilename condition=\"end with\">.cmd</TargetFilename> <!--Batch scripting | Credit @ion-storm -->\n\t\t\t<TargetFilename condition=\"end with\">.doc</TargetFilename> <!--Office doc potentially with macro -->\n\t\t\t<TargetFilename condition=\"end with\">.hta</TargetFilename> <!--Scripting-->\n\t\t\t<TargetFilename condition=\"end with\">.lnk</TargetFilename> <!--Shortcut file | Credit @ion-storm -->\n\t\t\t<TargetFilename condition=\"end with\">.ppt</TargetFilename> <!--Office doc potentially with macros-->\n\t\t\t<TargetFilename condition=\"end with\">.ps1</TargetFilename> <!--PowerShell-->\n\t\t\t<TargetFilename condition=\"end with\">.ps2</TargetFilename> <!--PowerShell-->\n\t\t\t<TargetFilename condition=\"end with\">.reg</TargetFilename> <!--Registry File-->\n\t\t\t<TargetFilename condition=\"end with\">.jse</TargetFilename> <!--Registry File-->\n\t\t\t<TargetFilename condition=\"end with\">.vb</TargetFilename> <!--VisualBasicScripting files-->\n\t\t\t<TargetFilename condition=\"end with\">.vbe</TargetFilename> <!--VisualBasicScripting files-->\n\t\t\t<TargetFilename condition=\"end with\">.vbs</TargetFilename> <!--VisualBasicScripting files-->\n\t\t</FileCreateStreamHash>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<FileCreateStreamHash onmatch=\"exclude\">\n\t\t</FileCreateStreamHash>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 16 : SYSMON CONFIGURATION CHANGE-->\n\t\t<!--EVENT 16: \"Sysmon config state changed\"-->\n\t\t<!--COMMENT:\tThis ONLY logs if the hash of the configuration changes. Running \"sysmon.exe -c\" with the current configuration will not be logged with Event 16-->\n\t\t\n\t\t<!--DATA: UtcTime, Configuration, ConfigurationFileHash-->\n\t\t<!--Cannot be filtered.-->\n\n\t<!--SYSMON EVENT ID 17 & 18 : PIPE CREATED / PIPE CONNECTED [PipeEvent]-->\n\t\t<!--EVENT 17: \"Pipe Created\"-->\n\t\t<!--EVENT 18: \"Pipe Connected\"-->\n\n\t\t<!--ADDITIONAL REFERENCE: [ https://www.cobaltstrike.com/help-smb-beacon ] -->\n\t\t<!--ADDITIONAL REFERENCE: [ https://blog.cobaltstrike.com/2015/10/07/named-pipe-pivoting/ ] -->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, PipeName, Image-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<PipeEvent onmatch=\"include\">\n\t\t\t<!--NOTE: Using incide with no rules means nothing in this section will be logged-->\n\t\t</PipeEvent>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 19 & 20 & 21 : WMI EVENT MONITORING [WmiEvent]-->\n\t\t<!--EVENT 19: \"WmiEventFilter activity detected\"-->\n\t\t<!--EVENT 20: \"WmiEventConsumer activity detected\"-->\n\t\t<!--EVENT 21: \"WmiEventConsumerToFilter activity detected\"-->\n\n\t\t<!--ADDITIONAL REFERENCE: [ https://www.darkoperator.com/blog/2017/10/15/sysinternals-sysmon-610-tracking-of-permanent-wmi-events ] -->\n\t\t<!--ADDITIONAL REFERENCE: [ https://rawsec.lu/blog/posts/2017/Sep/19/sysmon-v610-vs-wmi-persistence/ ] -->\n\n\t\t<!--DATA: EventType, UtcTime, Operation, User, Name, Type, Destination, Consumer, Filter-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<WmiEvent onmatch=\"exclude\">\n\t\t\t<!--NOTE: Using exclude with no rules means everything will be logged-->\n\t\t</WmiEvent>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 22 : DNS QUERY [DnsQuery]-->\n\t\t<!--EVENT 22: \"Dns query\"-->\n\n\t\t<!--NOTE:\tDue to the volume of events that DNS queries generate, some orgs may want to remove this section from their configuration to reduce Sysmon log turnover. -->\n\n\t\t<!--COMMENT:\tDNS logging is a very nuanced challenge in monitoring due to event volume. Legitimate domains can be used to host malware/C2, but lookup itself is not very informative.\n\t\t\t\t\t\tIt's fine to exclude monitoring these bulk low-value lookups, but at same time, you would not have a full log of how malware communicated, potentially missing C2.\n\t\t\t\t\t\tThis section of Sysmon configuration will require your full judgement and knowledge of your org's priorities. There is no correct answer.-->\n\n\t\t<!--OPERATIONS:\tChrome and Firefox prefetch DNS lookups, or use alternate DNS lookup methods Sysmon won't capture. You need to turn these off.\n\t\t\t\t\t\tSearch for Group Policy for these browsers to configure this.-->\n\n\t\t<!--OPERATIONS:\tMost DNS traffic is web advertising. To significantly reduce DNS queries and malware ads, enable client-side advertising filtering via Group Policy. This is easy.\n\t\t\t\tInternet Explorer: https://decentsecurity.com/adblocking-for-internet-explorer-deployment/\n\t\t\t\tChrome: https://decentsecurity.com/ublock-for-google-chrome-deployment/\n\t\t\t\tFirefox: ToDo\n\t\t\t\t\t\tAlso note, this configuration is designed for United States computers. Your country's users will may need customization to reduce noise.\n\t\t\t-->\n\n\t\t<!--CONFIG:\tDNS poisoning is an issue during threat investigations. Try to only exclude ROUTINE system-level queries you know are strongly validated with HTTPS or code signing.-->\n\t\t<!--CONFIG:\tIf you exclude microsoft.com, someone could register malware-microsoft.com and it wouldn't be logged. Use \"END WITH\" with leading . or \"IS\" operators.-->\n\t\t<!--CONFIG:\tBe very specific in exclusions. Threat actors use legitimate services, too. Dont exclude all of AWS or Azure or Google or CDNs!-->\n\t\t<!--CONFIG: Popularity data: [ http://s3-us-west-1.amazonaws.com/umbrella-static/index.html ] [ https://better.fyi/trackers/alexa-top-500-news/ ] -->\n\n\t\t<!--CRITICAL:\tDo NOT exclude \"wpad\" lookups. This is a MitM vector routinely used by attackers. Disable WPAD or enforce client-side DNSSEC for AD domain lookups.-->\n\t\t<!--CRITICAL:\tDo NOT exclude IPv6 lookups.-->\n\n\t\t<!--DATA: RuleName, UtcTime, ProcessGuid, ProcessId, QueryName, QueryType, QueryStatus, QueryResults (can't filter on)-->\n\n\t\t<!--BELOW: These domains should not be excluded at the top level. Be specific if you want to reduce noise under them.-->\n\t\t<!-- Rejected: .cloudapp.net, customer content [ https://blogs.technet.microsoft.com/ptsblog/2012/06/18/security-consideration-when-using-cloudapp-net-domain-as-production-environment-in-windows-azure/ ] -->\n\t\t<!-- Rejected: .googleapis.com, customer content [ https://www.zdnet.com/article/this-business-email-scam-spreads-trojans-through-google-cloud-storage/ ] -->\n\t\t<!-- Rejected: .cloudfront.net, customer content -->\n\t\t<!-- Rejected: .windows.net, customer content -->\n\t\t<!-- Rejected: *github.com, customer content, including open-source malware components -->\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<DnsQuery onmatch=\"exclude\">\n\t\t\t<!--Network noise-->\n\t\t\t<QueryName condition=\"end with\">.arpa.</QueryName> <!--Design decision to not log reverse DNS lookups. You will need to decide.-->\n\t\t\t<QueryName condition=\"end with\">.arpa</QueryName> <!--Design decision to not log reverse DNS lookups. You will need to decide.-->\n\t\t\t<QueryName condition=\"end with\">.msftncsi.com</QueryName> <!--Microsoft proxy detection | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"is\">..localmachine</QueryName>\n\t\t\t<QueryName condition=\"is\">localhost</QueryName>\n\t\t\t<!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">-pushp.svc.ms</QueryName> <!--Microsoft: Doesn't appear to host customer content or subdomains-->\n\t\t\t<QueryName condition=\"end with\">.b-msedge.net</QueryName> <!--Microsoft: Doesn't appear to host customer content or subdomains-->\n\t\t\t<QueryName condition=\"end with\">.bing.com</QueryName> <!-- Microsoft | Microsoft default exclusion -->\n\t\t\t<QueryName condition=\"end with\">.hotmail.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.live.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.live.net</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.s-microsoft.com</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">.microsoft.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.microsoftonline.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.microsoftstore.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.ms-acdc.office.com</QueryName> <!--Microsoft: Doesn't appear to host customer content or subdomains-->\n\t\t\t<QueryName condition=\"end with\">.msedge.net</QueryName> <!--Microsoft: Doesn't appear to host customer content or subdomains-->\n\t\t\t<QueryName condition=\"end with\">.msn.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.msocdn.com</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">.skype.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.skype.net</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.windows.com</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">.windows.net.nsatc.net</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">.windowsupdate.com</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">.xboxlive.com</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"is\">login.windows.net</QueryName> <!--Microsoft-->\n\t\t\t<Image condition=\"begin with\">C:\\ProgramData\\Microsoft\\Windows Defender\\Platform\\</Image> <!--Microsoft: https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/network-protection -->\n\t\t\t<!--Microsoft:Office365/AzureAD-->\n\t\t\t<QueryName condition=\"end with\">.activedirectory.windowsazure.com</QueryName> <!--Microsoft: AzureAD-->\n\t\t\t<QueryName condition=\"end with\">.aria.microsoft.com</QueryName> <!--Microsoft: OneDrive/SharePoint-->\n\t\t\t<QueryName condition=\"end with\">.msauth.net</QueryName>\n\t\t\t<QueryName condition=\"end with\">.msftauth.net</QueryName>\n\t\t\t<QueryName condition=\"end with\">.office.net</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"end with\">.opinsights.azure.com</QueryName> <!--Microsoft: AzureAD/InTune client event monitoring-->\n\t\t\t<QueryName condition=\"end with\">.res.office365.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">acdc-direct.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">atm-fp-direct.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">loki.delve.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">management.azure.com</QueryName> <!--Microsoft: AzureAD/InTune-->\n\t\t\t<QueryName condition=\"is\">messaging.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">outlook.office365.com</QueryName> <!--Microsoft: Protected by HSTS-->\n\t\t\t<QueryName condition=\"is\">portal.azure.com</QueryName> <!--Microsoft: AzureAD/InTune-->\n\t\t\t<QueryName condition=\"is\">protection.outlook.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">substrate.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"end with\">.measure.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<!--3rd-party applications-->\n\t\t\t<QueryName condition=\"end with\">.adobe.com</QueryName> <!--Adobe-->\n\t\t\t<QueryName condition=\"end with\">.adobe.io</QueryName> <!--Adobe-->\n\t\t\t<QueryName condition=\"end with\">.mozaws.net</QueryName> <!--Mozilla-->\n\t\t\t<QueryName condition=\"end with\">.mozilla.com</QueryName> <!--Mozilla-->\n\t\t\t<QueryName condition=\"end with\">.mozilla.net</QueryName> <!--Mozilla-->\n\t\t\t<QueryName condition=\"end with\">.mozilla.org</QueryName> <!--Mozilla-->\n\t\t\t<QueryName condition=\"end with\">.spotify.com</QueryName> <!--Spotify-->\n\t\t\t<QueryName condition=\"end with\">.spotify.map.fastly.net</QueryName> <!--Spotify-->\n\t\t\t<QueryName condition=\"end with\">.wbx2.com</QueryName> <!--Webex-->\n\t\t\t<QueryName condition=\"end with\">.webex.com</QueryName> <!--Webex-->\n\t\t\t<QueryName condition=\"is\">clients1.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clients2.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clients3.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clients4.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clients5.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clients6.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">safebrowsing.googleapis.com</QueryName> <!--Google-->\n\t\t\t<!--Goodlist CDN-->\n\t\t\t<QueryName condition=\"end with\">.akadns.net</QueryName> <!--AkamaiCDN, extensively used by Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.netflix.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">aspnetcdn.com</QueryName> <!--Microsoft [ https://docs.microsoft.com/en-us/aspnet/ajax/cdn/overview ]-->\n\t\t\t<QueryName condition=\"is\">ajax.googleapis.com</QueryName>\n\t\t\t<QueryName condition=\"is\">cdnjs.cloudflare.com</QueryName> <!--Cloudflare: Hosts popular javascript libraries-->\n\t\t\t<QueryName condition=\"is\">fonts.googleapis.com</QueryName> <!--Google fonts-->\n\t\t\t<QueryName condition=\"end with\">.typekit.net</QueryName> <!--Adobe fonts-->\n\t\t\t<QueryName condition=\"is\">cdnjs.cloudflare.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.stackassets.com</QueryName> <!--Stack Overflow-->\n\t\t\t<QueryName condition=\"end with\">.steamcontent.com</QueryName>\n\t\t\t<QueryName condition=\"is\">play.google.com</QueryName>\n\t\t\t<QueryName condition=\"is\">content-autofill.googleapis.com</QueryName>\n\t\t\t<!--Web resources-->\n\t\t\t<QueryName condition=\"end with\">.disqus.com</QueryName> <!--Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.fontawesome.com</QueryName>\n\t\t\t<QueryName condition=\"is\">disqus.com</QueryName> <!--Microsoft default exclusion-->\n\t\t\t<!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.1rx.io</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.2mdn.net</QueryName> <!--Ads: Google | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.3lift.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adadvisor.net</QueryName> <!--Ads: Neustar [ https://better.fyi/trackers/adadvisor.net/ ] -->\n\t\t\t<QueryName condition=\"end with\">.adap.tv</QueryName> <!--Ads:AOL | Microsoft default exclusion [ https://www.crunchbase.com/organization/adap-tv ] -->\n\t\t\t<QueryName condition=\"end with\">.addthis.com</QueryName> <!--Ads:Oracle | Microsoft default exclusion [ https://en.wikipedia.org/wiki/AddThis ] -->\n\t\t\t<QueryName condition=\"end with\">.adform.net</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adnxs.com</QueryName> <!--Ads: AppNexus | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.adroll.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adrta.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adsafeprotected.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adsrvr.org</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adsymptotic.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.advertising.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.agkn.com</QueryName> <!--Ads | [ https://www.home.neustar/privacy ] -->\n\t\t\t<QueryName condition=\"end with\">.amazon-adsystem.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.amazon-adsystem.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.analytics.yahoo.com</QueryName> <!--Ads:Yahoo-->\n\t\t\t<QueryName condition=\"end with\">.aol.com</QueryName> <!--Ads | Microsoft default exclusion -->\n\t\t\t<QueryName condition=\"end with\">.betrad.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.bidswitch.net</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.casalemedia.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.chartbeat.net</QueryName> <!--Ads | Microsoft default exclusion [ https://better.fyi/trackers/chartbeat.com/ ]-->\n\t\t\t<QueryName condition=\"end with\">.cnn.com</QueryName> <!-- Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.convertro.com</QueryName> <!--Ads:Verizon-->\n\t\t\t<QueryName condition=\"end with\">.criteo.com</QueryName> <!--Ads [ https://better.fyi/trackers/criteo.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.criteo.net</QueryName> <!--Ads [ https://better.fyi/trackers/criteo.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.crwdcntrl.net</QueryName> <!--Ads: Lotame [ https://better.fyi/trackers/crwdcntrl.net/ ] -->\n\t\t\t<QueryName condition=\"end with\">.demdex.net</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.domdex.com</QueryName> \n\t\t\t<QueryName condition=\"end with\">.dotomi.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.doubleclick.net</QueryName> <!--Ads:Conversant | Microsoft default exclusion [ https://www.crunchbase.com/organization/dotomi ] -->\n\t\t\t<QueryName condition=\"end with\">.doubleverify.com</QueryName> <!--Ads: Google-->\n\t\t\t<QueryName condition=\"end with\">.emxdgt.com</QueryName> <!--Ads: EMX-->\n\t\t\t<QueryName condition=\"end with\">.everesttech.net</QueryName> <!--Ads | [ https://better.fyi/trackers/everesttech.net/ ] -->\n\t\t\t<QueryName condition=\"end with\">.exelator.com</QueryName> <!--Ads:Nielson Marketing Cloud-->\n\t\t\t<QueryName condition=\"end with\">.google-analytics.com</QueryName> <!--Ads:Google | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.googleadservices.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"end with\">.googlesyndication.com</QueryName> <!--Ads:Google, sometimes called during malicious ads, but not directly responsible | Microsoft default exclusion [ https://www.hackread.com/wp-content/uploads/2018/06/Bitdefender-Whitepaper-Zacinlo.pdf ]-->\n\t\t\t<QueryName condition=\"end with\">.googletagmanager.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"end with\">.googlevideo.com</QueryName> <!--Google | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.gstatic.com</QueryName> <!--Google | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.gvt1.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"end with\">.gvt2.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"end with\">.ib-ibi.com</QueryName> <!--Ads: Offerpath [ https://better.fyi/trackers/ib-ibi.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.jivox.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.krxd.net</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.lijit.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.mathtag.com</QueryName> <!--Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.moatads.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.moatpixel.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.mookie1.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.myvisualiq.net</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.netmng.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.nexac.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.openx.net</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.optimizely.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.outbrain.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.pardot.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.phx.gbl</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.pinterest.com</QueryName> <!--Pinerest-->\n\t\t\t<QueryName condition=\"end with\">.pubmatic.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.quantcount.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.quantserve.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.revsci.net</QueryName> <!--Ads:Omniture | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.rfihub.net</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.rlcdn.com</QueryName> <!--Ads: Rapleaf [ https://better.fyi/trackers/rlcdn.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.rubiconproject.com</QueryName> <!--Ads: Rubicon Project | Microsoft default exclusion [ https://better.fyi/trackers/rubiconproject.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.scdn.co</QueryName> <!--Spotify-->\n\t\t\t<QueryName condition=\"end with\">.scorecardresearch.com</QueryName> <!--Ads: Comscore | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.serving-sys.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.sharethrough.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.simpli.fi</QueryName>\n\t\t\t<QueryName condition=\"end with\">.sitescout.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.smartadserver.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.snapads.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.spotxchange.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.taboola.com</QueryName> <!--Ads:Taboola-->\n\t\t\t<QueryName condition=\"end with\">.taboola.map.fastly.net</QueryName> <!--Ads:Taboola-->\n\t\t\t<QueryName condition=\"end with\">.tapad.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.tidaltv.com</QueryName> <!--Ads: Videology [ https://better.fyi/trackers/tidaltv.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.trafficmanager.net</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.tremorhub.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.tribalfusion.com</QueryName> <!--Ads: Exponential [ https://better.fyi/trackers/tribalfusion.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.turn.com</QueryName> <!--Ads | Microsoft default exclusion [ https://better.fyi/trackers/turn.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.twimg.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.tynt.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.w55c.net</QueryName> <!--Ads:dataxu-->\n\t\t\t<QueryName condition=\"end with\">.ytimg.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"end with\">.zorosrv.com</QueryName> <!--Ads:Taboola-->\n\t\t\t<QueryName condition=\"is\">1rx.io</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"is\">adservice.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">ampcid.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clientservices.googleapis.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">googleadapis.l.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">imasdk.googleapis.com</QueryName> <!--Google [ https://developers.google.com/interactive-media-ads/docs/sdks/html5/ ] -->\n\t\t\t<QueryName condition=\"is\">l.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">ml314.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"is\">mtalk.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">update.googleapis.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">www.googletagservices.com</QueryName> <!--Google-->\n\t\t\t<!--SocialNet-->\n\t\t\t<QueryName condition=\"end with\">.pscp.tv</QueryName> <!--Twitter:Periscope-->\n\t\t\t<!--OSCP/CRL Common-->\n\t\t\t<QueryName condition=\"end with\">.amazontrust.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.digicert.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.globalsign.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.globalsign.net</QueryName>\n\t\t\t<QueryName condition=\"end with\">.intel.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.symcb.com</QueryName> <!--Digicert-->\n\t\t\t<QueryName condition=\"end with\">.symcd.com</QueryName> <!--Digicert-->\n\t\t\t<QueryName condition=\"end with\">.thawte.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.usertrust.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.verisign.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">ocsp.identrust.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">pki.goog</QueryName>\n\t\t\t<QueryName condition=\"is\">msocsp.com</QueryName> <!--Microsoft:OCSP-->\n\t\t\t<QueryName condition=\"is\">ocsp.comodoca.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.entrust.net</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.godaddy.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.int-x3.letsencrypt.org</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.msocsp.com</QueryName> <!--Microsoft:OCSP-->\n\t\t\t<QueryName condition=\"end with\">pki.goog</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.godaddy.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">amazontrust.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.sectigo.com</QueryName>\n\t\t\t<QueryName condition=\"is\">pki-goog.l.google.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.usertrust.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.comodoca.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.verisign.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.entrust.net</QueryName>\n\t\t\t<QueryName condition=\"end with\">ocsp.identrust.com</QueryName>\n\t\t\t<QueryName condition=\"is\">status.rapidssl.com</QueryName>\n\t\t\t<QueryName condition=\"is\">status.thawte.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.int-x3.letsencrypt.org</QueryName>\n\t\t</DnsQuery>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 23 : FILE DELETE [FileDelete]-->\n\t\t<!--EVENT 22: \"File Delete\"-->\n\t\t<!--COMMENT:\tSandbox usage. When a program signals to Windows a file should be deleted or wiped, Sysmon may be able to capture it. \n\t\t\t[ https://isc.sans.edu/forums/diary/Sysmon+and+File+Deletion/26084/ ]\n\t\t-->\n\n\t\t<!--DATA: RuleName, UtcTime, ProcessGuid, ProcessId, User, Image, TargetFilename, Hashes, IsExecutable, Archived -->\n\n\t<!--\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ClipboardChange onmatch=\"include\">\n\t\t</ClipboardChange>\n\t</RuleGroup>\n\t-->\n\n\t<!--SYSMON EVENT ID 24 : CLIPBOARD EVENT MONITORING [ClipboardChange]-->\n\t\t<!--EVENT 24: \"Clipboard changed\"-->\n\t\t<!--COMMENT:\tSandbox usage.  Sysmon can capture the contents of clipboard events.\n\t\t\tAn  example of what could be a production usage on restricted desktops is provided below, but it is commented-out. -->\n\t\t\t\n\t\t<!--DATA: EventType, UtcTime, ProcessGuid, ProcessId, Image, Session, ClientInfo, Hashes, Archived -->\n\n\t<!--\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ClipboardChange onmatch=\"include\">\n\t\t\t<Image condition=\"end with\">wscript.exe</Image>\n\t\t\t<Image condition=\"end with\">cscript.exe</Image>\n\t\t\t<Image condition=\"end with\">powershell.exe</Image>\n\t\t\t<Image condition=\"end with\">rdpclip.exe</Image>\n\t\t</ClipboardChange>\n\t</RuleGroup>\n\t-->\n\n\t<!--SYSMON EVENT ID 25 : PROCESS TAMPERING [ProcessTampering]-->\n\t\t<!--EVENT 25: \"Process Tampering\"-->\n\t\t<!--COMMENT:\tThis event is generated when a process image is changed from an external source, such as a different process.\n\t\t\tThis may or may not provide value in your environment as it requires tuning and a SIEM to correlate the ProcessGuids.\n\t\t\t[ https://medium.com/falconforce/sysmon-13-process-tampering-detection-820366138a6c ] -->\n\t\t\n\t\t<!--DATA: EventType, RuleName, UtcTime, ProcessGuid, ProcessId, Image, Type -->\n\t\n\t<!--\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ProcessTampering onmatch=\"exclude\">\n\t\t\t<Image condition=\"begin with\">C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\</Image>\n\t\t</ProcessTampering>\n\t</RuleGroup>\n\t-->\n\n\t<!--SYSMON EVENT ID 255 : ERROR-->\n\t\t<!--\"This event is generated when an error occurred within Sysmon. They can happen if the system is under heavy load\n\t\t\tand certain tasked could not be performed or a bug exists in the Sysmon service. You can report any bugs on the\n\t\t\tSysinternals forum or over Twitter (@markrussinovich).\"-->\n\t\t<!--Cannot be filtered.-->\n\n\t</EventFiltering>\n</Sysmon>"
  },
  {
    "path": "ansible/roles/logs_windows/files/uninstall-service-winlogbeat.ps1",
    "content": "# Delete and stop the service if it already exists.\nif (Get-Service winlogbeat -ErrorAction SilentlyContinue) {\n  $service = Get-WmiObject -Class Win32_Service -Filter \"name='winlogbeat'\"\n  $service.StopService()\n  Start-Sleep -s 1\n  $service.delete()\n}\n"
  },
  {
    "path": "ansible/roles/logs_windows/handlers/main.yml",
    "content": "---\n- name: restart-winlogbeat\n  win_shell: Restart-Service winlogbeat"
  },
  {
    "path": "ansible/roles/logs_windows/tasks/main.yml",
    "content": "- name: Install winlogbeat\n  import_tasks: winlogbeat.yml\n\n- name: Set winlogbeat config file\n  win_copy:\n    src: winlogbeat.yml\n    dest: C:\\ProgramData\\chocolatey\\lib\\winlogbeat\\tools\\\n\n# sysmon install (https://github.com/NVISOsecurity/ansible-sysmon)\n- name: Create directory\n  win_file:\n    path: \"{{ sysmon_install_location }}\"\n    state: directory\n  register: result\n\n- name: Get sysmon zip\n  win_copy:\n    src: \"{{ sysmon_download_file }}{{ file_ext }}\"\n    dest: \"{{ sysmon_install_location }}/{{ sysmon_download_file }}{{ file_ext }}\"\n\n- name: Unzip sysmon\n  win_unzip:\n    src: \"{{ sysmon_install_location }}/{{ sysmon_download_file }}{{ file_ext }}\"\n    dest: \"{{ sysmon_install_location }}\"\n\n- name: Copy sysmon config\n  win_copy:\n    src: sysmonconfig-export.xml\n    dest: c:\\sysmon\\sysmonconfig-export.xml\n\n# RUN sysmon\n- name: check sysmon service\n  win_service:\n    name: sysmon64\n  register: result\n  failed_when: result is not defined\n  ignore_errors: yes\n\n- name: Run sysmon\n  win_command: \"{{ sysmon_install_location }}\\\\sysmon64.exe -accepteula -i {{ sysmon_install_location }}\\\\sysmonconfig-export.xml\"\n  args:\n    chdir: \"{{ sysmon_install_location }}\"\n  when: result.state is not defined or result.name is not defined\n\n# RUN winlogbeat\n- name: check winlogbeat service\n  win_service:\n    name: winlogbeat\n  register: resultwlb\n  failed_when: resultwlb is not defined\n  ignore_errors: yes\n\n- name: Reboot before launch setup\n  win_reboot:\n    reboot_timeout: 600\n    post_reboot_delay: 100\n  when: resultwlb.state is defined and resultwlb.state != 'running'\n\n- name: Run winlogbeat setup\n  win_command: \"winlogbeat setup -e\"\n  args:\n    chdir: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64\\\\\"\n  when: resultwlb.state is defined and resultwlb.state != 'running'\n\n# RUN winlogbeat\n- name: check winlogbeat service\n  win_service:\n    name: winlogbeat\n    start_mode: auto\n    state: started\n  when: resultwlb.state is defined and resultwlb.state != 'running'"
  },
  {
    "path": "ansible/roles/logs_windows/tasks/winlogbeat.yml",
    "content": "---\n# from https://github.com/j91321/ansible-role-winlogbeat\n- name: Create 64-bit install directory\n  win_file:\n    path: \"{{ winlogbeat_service.install_path_64 }}\"\n    state: directory\n\n- name: Check if winlogbeat service is installed\n  win_service:\n    name: winlogbeat\n  register: winlogbeat_installed\n\n- name: Check if winlogbeat is using current version\n  win_stat:\n    path: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64\"\n  register: winlogbeat_folder\n\n- name: Copy winlogbeat uninstall script\n  win_copy:\n    src: files/uninstall-service-winlogbeat.ps1\n    dest: \"{{ winlogbeat_service.install_path_64 }}\\\\uninstall-service-winlogbeat.ps1\"\n    force: yes\n  when: winlogbeat_installed.exists and not winlogbeat_folder.stat.exists\n\n- name: Uninstall winlogbeat\n  win_shell: .\\uninstall-service-winlogbeat.ps1\n  args:\n    chdir: \"{{ winlogbeat_service.install_path_64 }}\"\n  when: winlogbeat_installed.exists and not winlogbeat_folder.stat.exists\n\n- name: Download winlogbeat\n  win_get_url:\n    url: \"https://artifacts.elastic.co/downloads/beats/winlogbeat/winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64.zip\"\n    dest: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat.zip\"\n  when: winlogbeat_service.download and not winlogbeat_folder.stat.exists\n\n- name: Copy winlogbeat\n  win_copy:\n    src: \"files/winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64.zip\"\n    dest: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat.zip\"\n  when: not winlogbeat_service.download and not winlogbeat_folder.stat.exists\n\n- name: Unzip winlogbeat\n  win_unzip:\n    src: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat.zip\"\n    dest: \"{{ winlogbeat_service.install_path_64 }}\\\\\"\n    delete_archive: yes\n  when: not winlogbeat_folder.stat.exists\n\n- name: Configure winlogbeat\n  win_template:\n    src: winlogbeat.yml.j2\n    dest: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64\\\\winlogbeat.yml\"\n  notify: restart-winlogbeat\n\n- name: Install winlogbeat\n  win_shell: .\\install-service-winlogbeat.ps1\n  args:\n    chdir: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64\\\\\"\n  when: not winlogbeat_folder.stat.exists\n  notify: restart-winlogbeat\n\n- name: Remove other winlogbeat installations\n  win_shell: |\n    $version=\"{{ winlogbeat_service.version }}\"\n    Get-ChildItem -Path \"{{ winlogbeat_service.install_path_64 }}\" | Where-Object {$_.Name -CNotMatch $version} | Remove-Item -Recurse\n  when: not winlogbeat_folder.stat.exists\n"
  },
  {
    "path": "ansible/roles/logs_windows/templates/winlogbeat.yml.j2",
    "content": "###################### Winlogbeat Configuration Example ########################\n\n# This file is an example configuration file highlighting only the most common\n# options. The winlogbeat.reference.yml file from the same directory contains\n# all the supported options with more comments. You can use it as a reference.\n#\n# You can find the full configuration reference here:\n# https://www.elastic.co/guide/en/beats/winlogbeat/index.html\n\n# ======================== Winlogbeat specific options =========================\n\n# event_logs specifies a list of event logs to monitor as well as any\n# accompanying options. The YAML data type of event_logs is a list of\n# dictionaries.\n#\n# The supported keys are name (required), tags, fields, fields_under_root,\n# forwarded, ignore_older, level, event_id, provider, and include_xml. Please\n# visit the documentation for the complete details of each option.\n# https://go.es.io/WinlogbeatConfig\n\nwinlogbeat.event_logs:\n  - name: Application\n    ignore_older: 30m\n\n  - name: System\n\n  - name: Security\n    processors:\n      - script:\n          lang: javascript\n          id: security\n          file: ${path.home}/module/security/config/winlogbeat-security.js\n\n  - name: Microsoft-Windows-Sysmon/Operational\n    processors:\n      - script:\n          lang: javascript\n          id: sysmon\n          file: ${path.home}/module/sysmon/config/winlogbeat-sysmon.js\n\n  - name: Windows PowerShell\n    event_id: 400, 403, 600, 800\n    processors:\n      - script:\n          lang: javascript\n          id: powershell\n          file: ${path.home}/module/powershell/config/winlogbeat-powershell.js\n\n  - name: Microsoft-Windows-PowerShell/Operational\n    event_id: 4103, 4104, 4105, 4106\n    processors:\n      - script:\n          lang: javascript\n          id: powershell\n          file: ${path.home}/module/powershell/config/winlogbeat-powershell.js\n\n  - name: ForwardedEvents\n    tags: [forwarded]\n    processors:\n      - script:\n          when.equals.winlog.channel: Security\n          lang: javascript\n          id: security\n          file: ${path.home}/module/security/config/winlogbeat-security.js\n      - script:\n          when.equals.winlog.channel: Microsoft-Windows-Sysmon/Operational\n          lang: javascript\n          id: sysmon\n          file: ${path.home}/module/sysmon/config/winlogbeat-sysmon.js\n      - script:\n          when.equals.winlog.channel: Windows PowerShell\n          lang: javascript\n          id: powershell\n          file: ${path.home}/module/powershell/config/winlogbeat-powershell.js\n      - script:\n          when.equals.winlog.channel: Microsoft-Windows-PowerShell/Operational\n          lang: javascript\n          id: powershell\n          file: ${path.home}/module/powershell/config/winlogbeat-powershell.js\n  - name: Microsoft-Windows-WMI-Activity/Operational\n    event_id: 5857,5858,5859,5860,5861 \n# ====================== Elasticsearch template settings =======================\n\nsetup.template.settings:\n  index.number_of_shards: 1\n  #index.codec: best_compression\n  #_source.enabled: false\n\n\n# ================================== General ===================================\n\n# The name of the shipper that publishes the network data. It can be used to group\n# all the transactions sent by a single shipper in the web interface.\n#name:\n\n# The tags of the shipper are included in their own field with each\n# transaction published.\n#tags: [\"service-X\", \"web-tier\"]\n\n# Optional fields that you can specify to add additional information to the\n# output.\n#fields:\n#  env: staging\n\n# ================================= Dashboards =================================\n# These settings control loading the sample dashboards to the Kibana index. Loading\n# the dashboards is disabled by default and can be enabled either by setting the\n# options here or by using the `setup` command.\n#setup.dashboards.enabled: false\n\n# The URL from where to download the dashboards archive. By default this URL\n# has a value which is computed based on the Beat name and version. For released\n# versions, this URL points to the dashboard archive on the artifacts.elastic.co\n# website.\n#setup.dashboards.url:\n\n# =================================== Kibana ===================================\n\n# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API.\n# This requires a Kibana endpoint configuration.\nsetup.kibana:\n  host: \"{{ hostvars['elk'].ansible_host }}\"\n  # Kibana Host\n  # Scheme and port can be left out and will be set to the default (http and 5601)\n  # In case you specify and additional path, the scheme is required: http://localhost:5601/path\n  # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601\n  #host: \"localhost:5601\"\n\n  # Kibana Space ID\n  # ID of the Kibana Space into which the dashboards should be loaded. By default,\n  # the Default Space will be used.\n  #space.id:\n\n# =============================== Elastic Cloud ================================\n\n# These settings simplify using Winlogbeat with the Elastic Cloud (https://cloud.elastic.co/).\n\n# The cloud.id setting overwrites the `output.elasticsearch.hosts` and\n# `setup.kibana.host` options.\n# You can find the `cloud.id` in the Elastic Cloud web UI.\n#cloud.id:\n\n# The cloud.auth setting overwrites the `output.elasticsearch.username` and\n# `output.elasticsearch.password` settings. The format is `<user>:<pass>`.\n#cloud.auth:\n\n# ================================== Outputs ===================================\n\n# Configure what output to use when sending the data collected by the beat.\n\n# ---------------------------- Elasticsearch Output ----------------------------\noutput.elasticsearch:\n  # Array of hosts to connect to.\n  hosts: [\"{{ hostvars['elk'].ansible_host }}:9200\"]\n  username: \"elastic\"\n  password: \"changeme\"\n\n  # Protocol - either `http` (default) or `https`.\n  #protocol: \"https\"\n\n  # Authentication credentials - either API key or username/password.\n  #api_key: \"id:api_key\"\n  #username: \"elastic\"\n  #password: \"changeme\"\n\n# ------------------------------ Logstash Output -------------------------------\n#output.logstash:\n  # The Logstash hosts\n  #hosts: [\"localhost:5044\"]\n\n  # Optional SSL. By default is off.\n  # List of root certificates for HTTPS server verifications\n  #ssl.certificate_authorities: [\"/etc/pki/root/ca.pem\"]\n\n  # Certificate for SSL client authentication\n  #ssl.certificate: \"/etc/pki/client/cert.pem\"\n\n  # Client Certificate Key\n  #ssl.key: \"/etc/pki/client/cert.key\"\n\n# ================================= Processors =================================\nprocessors:\n  - add_host_metadata:\n      when.not.contains.tags: forwarded\n  - add_cloud_metadata: ~\n\n# ================================== Logging ===================================\n\n# Sets log level. The default log level is info.\n# Available log levels are: error, warning, info, debug\n#logging.level: debug\n\n# At debug level, you can selectively enable logging only for some components.\n# To enable all selectors use [\"*\"]. Examples of other selectors are \"beat\",\n# \"publisher\", \"service\".\n#logging.selectors: [\"*\"]\n\n# ============================= X-Pack Monitoring ==============================\n# Winlogbeat can export internal metrics to a central Elasticsearch monitoring\n# cluster.  This requires xpack monitoring to be enabled in Elasticsearch.  The\n# reporting is disabled by default.\n\n# Set to true to enable the monitoring reporter.\n#monitoring.enabled: false\n\n# Sets the UUID of the Elasticsearch cluster under which monitoring data for this\n# Winlogbeat instance will appear in the Stack Monitoring UI. If output.elasticsearch\n# is enabled, the UUID is derived from the Elasticsearch cluster referenced by output.elasticsearch.\n#monitoring.cluster_uuid:\n\n# Uncomment to send the metrics to Elasticsearch. Most settings from the\n# Elasticsearch output are accepted here as well.\n# Note that the settings should point to your Elasticsearch *monitoring* cluster.\n# Any setting that is not set is automatically inherited from the Elasticsearch\n# output configuration, so if you have the Elasticsearch output configured such\n# that it is pointing to your Elasticsearch monitoring cluster, you can simply\n# uncomment the following line.\n#monitoring.elasticsearch:\n\n# ============================== Instrumentation ===============================\n\n# Instrumentation support for the winlogbeat.\n#instrumentation:\n    # Set to true to enable instrumentation of winlogbeat.\n    #enabled: false\n\n    # Environment in which winlogbeat is running on (eg: staging, production, etc.)\n    #environment: \"\"\n\n    # APM Server hosts to report instrumentation results to.\n    #hosts:\n    #  - http://localhost:8200\n\n    # API Key for the APM Server(s).\n    # If api_key is set then secret_token will be ignored.\n    #api_key:\n\n    # Secret token for the APM Server(s).\n    #secret_token:\n\n\n# ================================= Migration ==================================\n\n# This allows to enable 6.7 migration aliases\n#migration.6_to_7.enabled: true\n"
  },
  {
    "path": "ansible/roles/member_server/tasks/main.yml",
    "content": "# DNSCHANGE\n- name: \"prioritize the {{domain_adapter}} interface (local) as the default for routing\"\n  ansible.windows.win_shell:\n    Set-NetIPInterface -InterfaceAlias \"{{domain_adapter}}\" -InterfaceMetric 10\n  when: two_adapters\n\n- name: \"Set configure dns to {{dns_domain}}\"\n  win_dns_client:\n    adapter_names: \"{{domain_adapter}}\"\n    ipv4_addresses:\n    - \"{{hostvars[dns_domain].ansible_host}}\"\n    log_path: C:\\dns_log.txt\n\n- name: Verify File Server Role is installed.\n  win_feature:\n    name: File-Services, FS-FileServer\n    state: present\n    include_management_tools: True\n\n- name: \"Add member server\"\n  win_domain_membership:\n    dns_domain_name: \"{{member_domain}}\"\n    domain_admin_user: \"{{domain_username}}\"\n    domain_admin_password: \"{{domain_password}}\"\n#    domain_ou_path: \"{{member_domain_ou_path}}\"\n    state: domain\n  register: domain_state\n\n- name: Reboot if needed\n  win_reboot:\n    reboot_timeout: 1500\n    post_reboot_delay: 100\n  when: domain_state.reboot_required\n\n"
  },
  {
    "path": "ansible/roles/move_to_ou/tasks/main.yml",
    "content": "# only for not laps computer as they are automatically moved during the laps OU creation\n- name: Move computer to OU\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $hostname,\n\n          [String]\n          $ou_path\n      )\n      try {\n        $Ansible.Changed = $false\n        $target_ou = Get-ADOrganizationalUnit -Identity $ou_path > $null\n        $server = Get-AdComputer -Identity $hostname\n        $actual_location = ($server.DistinguishedName.split(',')| select -Skip 1) -join ','\n        if (($actual_location -eq \"CN=Computers,\" + $target_ou.DistinguishedName) -Or ($actual_location -eq $target_ou.DistinguishedName)) {\n          $Ansible.Changed = $false\n        } else {\n          Move-ADObject -Identity $server.DistinguishedName -TargetPath $ou_path\n          $Ansible.Changed = $true\n        }\n      } catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {\n        $Ansible.Changed = $false\n      }\n    parameters:\n      hostname: \"{{item.value.hostname}}\"\n      ou_path:  \"{{item.value.path|default('')}}\"\n  when: item.value.type != 'dc' and member_domain == item.value.domain and (item.value.use_laps is not defined or item.value.use_laps != true)\n  with_dict: \"{{hosts_dict}}\""
  },
  {
    "path": "ansible/roles/mssql/defaults/main.yml",
    "content": "# GOAD / NHA\nsql_instance_name: SQLEXPRESS\nsql_version: MSSQL_2019\n\n# SCCM\n#sql_instance_name: MSSQLSERVER\n#sql_version: MSSQL_2022\n\n# SQL2019-SSEI-Expr.exe\ndownload_url_2019: https://download.microsoft.com/download/7/f/8/7f8a9c43-8c8a-4f7c-9f92-83c18d96b681/SQL2019-SSEI-Expr.exe\n# SQL2022-SSEI-Eval.exe\ndownload_url_2022: https://go.microsoft.com/fwlink/?linkid=2215202&clcid=0x409&culture=en-us&country=us\n\nconnection_type_2019: \"-E\"\nconnection_type_2022: \"-S 127.0.0.1,1433\""
  },
  {
    "path": "ansible/roles/mssql/files/sql_conf.ini.MSSQL_2019.j2",
    "content": "#jinja2: newline_sequence:\"\\r\\n\"\n;SQL Server Configuration File\n[OPTIONS]\nIACCEPTSQLSERVERLICENSETERMS=\"True\"\nACTION=\"Install\"\nENU=\"True\"\nQUIET=\"True\"\nQUIETSIMPLE=\"False\"\nUpdateEnabled=\"False\"\nERRORREPORTING=\"False\"\nUSEMICROSOFTUPDATE=\"False\"\nFEATURES=SQLENGINE,FULLTEXT\nUpdateSource=\"MU\"\nHELP=\"False\"\nINDICATEPROGRESS=\"False\"\nX86=\"False\"\nINSTALLSHAREDDIR=\"C:\\Program Files\\Microsoft SQL Server\"\nINSTALLSHAREDWOWDIR=\"C:\\Program Files (x86)\\Microsoft SQL Server\"\nINSTANCENAME=\"{{ sql_instance_name }}\"\nSQMREPORTING=\"False\"\nINSTANCEID=\"{{ sql_instance_name }}\"\nRSINSTALLMODE=\"DefaultNativeMode\"\nINSTANCEDIR=\"C:\\Program Files\\Microsoft SQL Server\"\nAGTSVCACCOUNT=\"NT AUTHORITY\\NETWORK SERVICE\"\nAGTSVCSTARTUPTYPE=\"Automatic\"\nCOMMFABRICPORT=\"0\"\nCOMMFABRICNETWORKLEVEL=\"0\"\nCOMMFABRICENCRYPTION=\"0\"\nMATRIXCMBRICKCOMMPORT=\"0\"\nSQLSVCSTARTUPTYPE=\"Automatic\"\nFILESTREAMLEVEL=\"0\"\nENABLERANU=\"False\"\nSQLCOLLATION=\"SQL_Latin1_General_CP1_CI_AS\"\nSQLSVCACCOUNT=\"{{ SQLSVCACCOUNT }}\"\n{% if SQLSVCPASSWORD != \"\" %}\nSQLSVCPASSWORD=\"{{ SQLSVCPASSWORD }}\"\n{% endif %}\nSAPWD=\"{{sa_password}}\"\nSQLSYSADMINACCOUNTS=\"{{ SQLYSADMIN }}\"\nADDCURRENTUSERASSQLADMIN=\"True\"\nTCPENABLED=\"1\"\nNPENABLED=\"0\"\nBROWSERSVCSTARTUPTYPE=\"Disabled\"\nRSSVCSTARTUPTYPE=\"manual\"\nFTSVCACCOUNT=\"NT Service\\MSSQLFDLauncher\""
  },
  {
    "path": "ansible/roles/mssql/files/sql_conf.ini.MSSQL_2022.j2",
    "content": "#jinja2: newline_sequence:\"\\r\\n\"\n;SQL Server Configuration File\n[OPTIONS]\nIACCEPTSQLSERVERLICENSETERMS=\"True\"\nACTION=\"Install\"\nENU=\"True\"\nQUIET=\"True\"\nQUIETSIMPLE=\"False\"\nUpdateEnabled=\"False\"\nERRORREPORTING=\"False\"\nUSEMICROSOFTUPDATE=\"False\"\nFEATURES=SQLENGINE,FULLTEXT\nUpdateSource=\"MU\"\nHELP=\"False\"\nINDICATEPROGRESS=\"False\"\n; X86=\"False\"\nINSTALLSHAREDDIR=\"C:\\Program Files\\Microsoft SQL Server\"\nINSTALLSHAREDWOWDIR=\"C:\\Program Files (x86)\\Microsoft SQL Server\"\nINSTANCENAME=\"{{ sql_instance_name }}\"\nSQMREPORTING=\"False\"\nINSTANCEID=\"{{ sql_instance_name }}\"\n; RSINSTALLMODE=\"DefaultNativeMode\"\nINSTANCEDIR=\"C:\\Program Files\\Microsoft SQL Server\"\nAGTSVCACCOUNT=\"NT AUTHORITY\\NETWORK SERVICE\"\nAGTSVCSTARTUPTYPE=\"Automatic\"\n; COMMFABRICPORT=\"0\"\n; COMMFABRICNETWORKLEVEL=\"0\"\n; COMMFABRICENCRYPTION=\"0\"\n; MATRIXCMBRICKCOMMPORT=\"0\"\nSQLSVCSTARTUPTYPE=\"Automatic\"\nFILESTREAMLEVEL=\"0\"\nENABLERANU=\"False\"\nSQLCOLLATION=\"SQL_Latin1_General_CP1_CI_AS\"\nSQLSVCACCOUNT=\"{{ SQLSVCACCOUNT }}\"\n{% if SQLSVCPASSWORD != \"\" %}\nSQLSVCPASSWORD=\"{{ SQLSVCPASSWORD }}\"\n{% endif %}\nSAPWD=\"{{sa_password}}\"\nSQLSYSADMINACCOUNTS=\"{{ SQLYSADMIN }}\"\n;ADDCURRENTUSERASSQLADMIN=\"True\"\nADDCURRENTUSERASSQLADMIN=\"False\"\nTCPENABLED=\"1\"\nNPENABLED=\"0\"\nBROWSERSVCSTARTUPTYPE=\"Disabled\"\n; RSSVCSTARTUPTYPE=\"manual\"\n; FTSVCACCOUNT=\"NT Service\\MSSQLFDLauncher\""
  },
  {
    "path": "ansible/roles/mssql/tasks/main.yml",
    "content": "- name: Reboot before install (long timeout in case of update)\n  win_reboot:\n    reboot_timeout: 1200\n\n- name: Set download_url\n  set_fact:\n    download_url: \"{{ download_url_2022 if sql_version == 'MSSQL_2022' else download_url_2019}}\"\n\n- name: Set connection method\n  set_fact:\n    connection_type: \"{{ connection_type_2022 if sql_version == 'MSSQL_2022' else connection_type_2019}}\"\n\n- name: Set mssql_service_instance\n  set_fact:\n    mssql_service_instance: \"MSSQL${{ sql_instance_name }}\"\n\n- name: Set mssql_service_name\n  set_fact:\n    mssql_service_name: \"{{ mssql_service_instance if sql_instance_name != 'MSSQLSERVER' else 'MSSQLSERVER' }}\"\n\n- name: Display mssql variables in use\n  ansible.builtin.debug:\n    msg: \n    - \"MSSQL version        : {{ sql_version }}\"\n    - \"MSSQL service name   : {{ mssql_service_name }}\"\n    - \"MSSQL download url   : {{ download_url }}\"\n    - \"MSSQL instance       : {{ sql_instance_name }}\"\n    - \"MSSQL connection use : {{ connection_type }}\"\n\n- name: create a directory for installer download\n  win_file: \n    path: c:\\setup\n    state: directory\n\n- name: create a directory for installer extraction\n  win_file: \n    path: c:\\setup\\mssql\n    state: directory\n\n- name: create a directory for media extraction\n  win_file: \n    path: c:\\setup\\mssql\\media\n    state: directory\n\n- name: create the configuration file\n  win_template: \n    src: files/sql_conf.ini.{{sql_version}}.j2\n    dest: c:\\setup\\mssql\\sql_conf.ini\n\n- name: check downloaded file exists\n  win_stat:\n    path: c:\\setup\\mssql\\sql_installer.exe\n  register: installer_file\n\n- name: get the installer\n  win_get_url:\n      url: \"{{download_url}}\"\n      dest: 'c:\\setup\\mssql\\sql_installer.exe'\n  when: not installer_file.stat.exists\n\n- name: Add service account to Log on as a service\n  win_user_right:\n    name: SeServiceLogonRight\n    users:\n    - '{{ SQLSVCACCOUNT }}'\n    action: add\n  when: not SQLSVCACCOUNT == \"NT AUTHORITY\\\\NETWORK SERVICE\"\n\n# - name: Setup service account\n# Set-ADUser -Identity \"{{SQLSVCACCOUNT}}\" -ServicePrincipalNames @{Add='MSSQLSvc/castelblack.north.sevenkingdoms.local'}\n# Get-ADUser -Identity \"{{SQLSVCACCOUNT}}\" | Set-ADAccountControl -TrustedToAuthForDelegation $true\n# Set-ADUser -Identity \"{{SQLSVCACCOUNT}}\" -Add @{'msDS-AllowedToDelegateTo'=@('CIFS/winterfell.north.sevenkingdoms.local','CIFS/winterfell')}\n\n# - name: check install already done\n#   win_stat:\n#     path: \"C:\\\\Program Files\\\\Microsoft SQL Server\\\\MSSQL15.{{sql_instance_name}}\"\n#   register: mssql_install_already_done\n\n- name: check MSSQL service already exist (if failed service do not exist, launch install)\n  win_service:\n    name: '{{mssql_service_name}}'\n  register: mssql_install_already_done\n  failed_when: mssql_install_already_done is not defined\n  ignore_errors: yes\n\n- debug: msg=\"{{mssql_install_already_done}}\"\n\n# Install the database with a domain admin user\n- name: Install the database\n  win_command: c:\\setup\\mssql\\sql_installer.exe /configurationfile=c:\\setup\\mssql\\sql_conf.ini /IACCEPTSQLSERVERLICENSETERMS /MEDIAPATH=c:\\setup\\mssql\\media /QUIET /HIDEPROGRESSBAR\n  args:\n    chdir: c:\\setup\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_admin}}\"\n    ansible_become_password: \"{{domain_admin_password}}\"\n    ansible_become_flags: logon_type=new_credentials logon_flags=netcredentials_only\n  register: mssqlinstall\n  until: \"mssqlinstall is not failed\"\n  retries: 3\n  delay: 120\n  when: mssql_install_already_done.state is not defined or mssql_install_already_done.name is not defined\n#  when: not mssql_install_already_done.stat.exists\n\n# sql server 2022\n- name: Add or update registry for ip port\n  win_regedit:\n    path: 'HKLM:\\Software\\Microsoft\\Microsoft SQL Server\\MSSQL16.{{ sql_instance_name }}\\MSSQLServer\\SuperSocketNetLib\\Tcp\\IPAll'\n    name: TcpPort\n    data: 1433\n  register: win_reg\n  when: sql_version == \"MSSQL_2022\"\n\n# sql server 2019\n- name: Add or update registry for ip port\n  win_regedit:\n    path: 'HKLM:\\Software\\Microsoft\\Microsoft SQL Server\\MSSQL15.{{ sql_instance_name }}\\MSSQLServer\\SuperSocketNetLib\\Tcp\\IPAll'\n    name: TcpPort\n    data: 1433\n  register: win_reg\n  when: sql_version == \"MSSQL_2019\"\n\n- name: Reboot\n  win_reboot:\n  when: win_reg.changed\n\n- name: Firewall | Allow MSSQL through Firewall\n  win_dsc:\n    resource_name: xFirewall\n    Name: \"Access for MSSQL (TCP-In)\"\n    Ensure: present\n    Enabled: True\n    Profile: \"Domain\"\n    Direction: \"Inbound\"\n    Localport: \"1433\"\n    Protocol: \"TCP\"\n    Description: \"Opens the listener port for MSSQL\"\n\n- name: Firewall | Allow MSSQL discover through Firewall\n  win_dsc:\n    resource_name: xFirewall\n    Name: \"Access for MSSQL (UDP-In)\"\n    Ensure: present\n    Enabled: True\n    Profile: \"Domain\"\n    Direction: \"Inbound\"\n    Localport: \"1434\"\n    Protocol: \"UDP\"\n    Description: \"Opens the discover port for MSSQL\"\n\n- name: Be sure service is started\n  win_service:\n    name: '{{mssql_service_name}}'\n    force_dependent_services: yes\n    state: started\n\n- name: Wait for port 1433 to become open on the host, start checking every 5 seconds\n  ansible.windows.win_wait_for:\n    port: 1433\n    delay: 5\n\n- name: Add MSSQL admin\n  win_shell: |\n    SqlCmd {{connection_type}} -Q \"CREATE LOGIN [{{item}}] FROM WINDOWS\"\n    SqlCmd {{connection_type}} -Q \"SP_ADDSRVROLEMEMBER '{{item}}','SYSADMIN'\"\n  become: yes\n  become_method: runas\n  become_user: \"{{SQLSVCACCOUNT}}\"\n  vars:\n    ansible_become_pass: \"{{SQLSVCPASSWORD}}\"\n  loop: \"{{sql_sysadmins}}\"\n\n- name: Add IMPERSONATE on login\n  win_shell: |\n    SqlCmd {{connection_type}} -Q \"CREATE LOGIN [{{item.key}}] FROM WINDOWS\"\n    SqlCmd {{connection_type}} -Q \"GRANT IMPERSONATE ON LOGIN::[{{item.value}}] TO [{{item.key}}]\"\n  become: yes\n  become_method: runas\n  become_user: \"{{SQLSVCACCOUNT}}\"\n  vars:\n    ansible_become_pass: \"{{SQLSVCPASSWORD}}\"\n  with_dict: \"{{executeaslogin}}\"\n\n- name: Add IMPERSONATE on user\n  win_shell: |\n    SqlCmd {{connection_type}} -Q \"CREATE LOGIN [{{item.key}}] FROM WINDOWS\"\n    SqlCmd {{connection_type}} -Q \"USE {{item.value.db}};CREATE USER [{{item.value.user}}] FOR LOGIN [{{item.value.user}}]\"\n    SqlCmd {{connection_type}} -Q \"USE {{item.value.db}};GRANT IMPERSONATE ON USER::[{{item.value.impersonate}}] TO [{{item.value.user}}]\"\n  become: yes\n  become_method: runas\n  become_user: \"{{SQLSVCACCOUNT}}\"\n  vars:\n    ansible_become_pass: \"{{SQLSVCPASSWORD}}\"\n  with_dict: \"{{executeasuser}}\"\n\n- name: Enable sa account\n  win_shell: |\n    SqlCmd {{connection_type}} -Q \"ALTER LOGIN sa ENABLE\"\n    SqlCmd {{connection_type}} -Q \"ALTER LOGIN sa WITH PASSWORD = '{{sa_password}}' , CHECK_POLICY=OFF\"\n  become: yes\n  become_method: runas\n  become_user: \"{{SQLSVCACCOUNT}}\"\n  vars:\n    ansible_become_pass: \"{{SQLSVCPASSWORD}}\"\n\n- name: enable MSSQL authentication and windows authent\n  win_shell: |\n    SqlCmd {{connection_type}} -Q \"EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\\Microsoft\\MSSQLServer\\MSSQLServer', N'LoginMode', REG_DWORD, 2\"\n  become: yes\n  become_method: runas\n  become_user: \"{{SQLSVCACCOUNT}}\"\n  vars:\n    ansible_become_pass: \"{{SQLSVCPASSWORD}}\"\n\n- name: Restart service MSSQL\n  win_service:\n    name: '{{mssql_service_name}}'\n    force_dependent_services: yes\n    state: restarted\n"
  },
  {
    "path": "ansible/roles/mssql_link/tasks/logins.yml",
    "content": "- name: Create logins mapping to specific users\n  win_shell: |\n    SqlCmd -E -Q \"EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'{{linked_server}}', @locallogin = N'{{user_mapping.local_login}}', @useself = N'False', @rmtuser = N'{{user_mapping.remote_login}}', @rmtpassword = N'{{user_mapping.remote_password}}'\"\n  become: yes\n  become_method: runas\n  become_user: \"{{SQLSVCACCOUNT}}\"\n  vars:\n    ansible_become_pass: \"{{SQLSVCPASSWORD}}\"\n  loop: \"{{users_mapping}}\"\n  loop_control:\n    loop_var: user_mapping"
  },
  {
    "path": "ansible/roles/mssql_link/tasks/main.yml",
    "content": "- name: Create SQL Linked server and enable RPC\n  win_shell: |\n    SqlCmd -E -Q \"EXEC master.dbo.sp_addlinkedserver @server = N'{{item.key}}', @srvproduct=N'', @provider=N'SQLOLEDB', @datasrc=N'{{item.value.data_src}}'\"\n    SqlCmd -E -Q \"EXEC master.dbo.sp_serveroption @server=N'{{item.key}}', @optname=N'rpc', @optvalue=N'true'\"\n    SqlCmd -E -Q \"EXEC master.dbo.sp_serveroption @server=N'{{item.key}}', @optname=N'rpc out', @optvalue=N'true'\"\n  become: yes\n  become_method: runas\n  become_user: \"{{SQLSVCACCOUNT}}\"\n  vars:\n    ansible_become_pass: \"{{SQLSVCPASSWORD}}\"\n  with_dict: \"{{linked_servers}}\"\n\n#- name: Create logins mapping to specific users\n#  win_shell: |\n#    SqlCmd -E -Q \"EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'{{item.key}}', @locallogin = N'{{item.value.local_login}}', @useself = N'False', @rmtuser = N'{{item.value.remote_login}}', @rmtpassword = N'{{item.value.remote_password}}'\"\n#  become: yes\n#  become_method: runas\n#  become_user: \"{{SQLSVCACCOUNT}}\"\n#  vars:\n#    ansible_become_pass: \"{{SQLSVCPASSWORD}}\"\n#  with_dict: \"{{linked_servers.users_mapping}}\"\n\n- name: \"create logins\"\n  include_tasks: logins.yml  \n  vars:\n    linked_server: \"{{item.key}}\"\n    users_mapping: \"{{item.value.users_mapping}}\"\n  with_dict: \"{{linked_servers}}\"\n\n- name: default login impersonation\n  win_shell: |\n    SqlCmd -E -Q \"EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'{{item.key}}', @locallogin = NULL , @useself = N'True'\"\n  become: yes\n  become_method: runas\n  become_user: \"{{SQLSVCACCOUNT}}\"\n  vars:\n    ansible_become_pass: \"{{SQLSVCPASSWORD}}\"\n  with_dict: \"{{linked_servers}}\"\n"
  },
  {
    "path": "ansible/roles/mssql_reporting/tasks/main.yml",
    "content": "- name: create directory to store the install files\n  ansible.windows.win_file:\n    path: C:\\setup\n    state: directory\n\n- name: create directory to store the install files\n  ansible.windows.win_file:\n    path: C:\\setup\\mssql_reporting\n    state: directory\n\n- name: Reporting Services 2022 exists\n  win_stat:\n    path: C:\\setup\\mssql_reporting\\SQLServerReportingServices.exe\n  register: rs_installer_file\n\n- name: download SQL Server 2022 Reporting Services\n  ansible.windows.win_get_url:\n    url: https://download.microsoft.com/download/8/3/2/832616ff-af64-42b5-a0b1-5eb07f71dec9/SQLServerReportingServices.exe\n    dest: C:\\setup\\mssql_reporting\\SQLServerReportingServices.exe\n  when: not rs_installer_file.stat.exists\n\n- name: install SQL Server 2022 Reporting Services\n  win_shell: .\\SQLServerReportingServices.exe /IAcceptLicenseTerms /quiet\n  args:\n    chdir: C:\\setup\\mssql_reporting\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_admin}}\"\n    ansible_become_password: \"{{domain_admin_password}}\""
  },
  {
    "path": "ansible/roles/mssql_ssms/tasks/main.yml",
    "content": "- name: check SQL Server Manager Studio installer exists\n  win_stat:\n    path: c:\\setup\\mssql\\SSMS_installer.exe\n  register: ssms_installer_file\n\n- name: get the installer\n  win_get_url:\n      url: 'https://aka.ms/ssmsfullsetup'\n      dest: 'c:\\setup\\mssql\\SSMS_installer.exe'\n  when: not ssms_installer_file.stat.exists\n\n- name: check SSMS installation already done\n  win_stat:\n    path: \"C:\\\\Program Files (x86)\\\\Microsoft SQL Server Management Studio 18\"\n  register: ssms_installation\n\n- name: Install SSMS\n  win_command: c:\\setup\\mssql\\SSMS_installer.exe /install /quiet /norestart\n  register: install_ssmss\n  when: not ssms_installation.stat.exists\n\n- name: Reboot after install\n  win_reboot:\n    reboot_timeout: 600\n  when: not ssms_installation.stat.exists"
  },
  {
    "path": "ansible/roles/onlyusers/tasks/main.yml",
    "content": "- name: \"Create users\"\n  community.windows.win_domain_user:\n    name: \"{{ item.key }}\"\n    firstname: \"{{item.value.firstname}}\"\n    surname: \"{{ item.value.surname }}\"\n    password: \"{{ item.value.password }}\"\n    password_never_expires: yes\n    state: present\n    path: \"{{item.value.path}}\"\n    description: \"{{item.value.description}}\"\n    groups: \"{{ item.value.groups}}\"\n    city: \"{{item.value.city}}\"\n    domain_username: \"{{domain_username}}\"\n    domain_password: \"{{domain_password}}\"\n  with_dict: \"{{ ad_users }}\""
  },
  {
    "path": "ansible/roles/parent_child_dns/tasks/main.yml",
    "content": "---\n#- name: Create A record for child domain in parent domain\n#  community.windows.win_dns_record:\n#    name: \"{{lab.hosts[dc].hostname}}.{{item.split('.')[0]}}\"\n#    type: \"A\"\n#    values:\n#      - \"{{hostvars[dc].ansible_host}}\"\n#    zone: \"{{domain}}\"\n#  vars:\n#    dc: \"{{lab.domains[item].dc}}\"\n#  loop: \"{{ domains }}\"\n#  when: domain == '.'.join(item.split('.')[1:])\n\n\n# set delegation to child domain\n# Add-DnsServerZoneDelegation -Name \"sevenkingdoms.local\" -ChildZoneName \"north\" -NameServer \"winterfell.north.sevenkingdoms.local\" -IPAddress 192.168.10.11 -PassThru -Verbose\n# domain == parent domain\n# item == child domain\n- name: add dns delegation to child domain\n  ansible.windows.win_shell: |\n    Add-DnsServerZoneDelegation -Name \"{{parent_domain}}\" -ChildZoneName \"{{zone}}\" -NameServer \"{{name_server}}\" -IPAddress \"{{name_server_ip}}\" -PassThru -Verbose\n  vars:\n    parent_domain: \"{{domain}}\"\n    child_dc: \"{{lab.domains[item].dc}}\"\n    name_server: \"{{lab.hosts[child_dc].hostname}}.{{item}}\"\n    name_server_ip: \"{{hostvars[child_dc].ansible_host}}\"\n    zone: \"{{item.split('.')[0]}}\"\n  loop: \"{{ domains }}\"\n  when: domain == '.'.join(item.split('.')[1:])\n\n\n- name: create conditional forwarder to child domain\n  community.windows.win_dns_zone:\n    name: \"{{item}}\"\n    type: forwarder\n    replication: \"none\"\n    dns_servers:\n      - \"{{name_server_ip}}\"\n  vars:\n    child_dc: \"{{lab.domains[item].dc}}\"\n    name_server_ip: \"{{hostvars[child_dc].ansible_host}}\"\n    zone: \"{{item.split('.')[0]}}\"\n  loop: \"{{ domains }}\"\n  when: domain == '.'.join(item.split('.')[1:])\n\n\n"
  },
  {
    "path": "ansible/roles/password_policy/tasks/main.yml",
    "content": "- name: set password policy\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $LockoutThreshold,\n\n          [String]\n          $MinPasswordLength,\n\n          [String]\n          $LockoutDuration,\n\n          [String]\n          $LockoutObservationWindow,\n\n          [Boolean]\n          $ComplexityEnabled\n      )\n      $Domain = (gwmi WIN32_ComputerSystem).Domain\n      Set-ADDefaultDomainPasswordPolicy -Identity $Domain -AuthType Negotiate -LockoutDuration $LockoutDuration -LockoutObservationWindow $LockoutObservationWindow -LockoutThreshold $LockoutThreshold -ComplexityEnabled $ComplexityEnabled -ReversibleEncryptionEnabled $False -MinPasswordLength $MinPasswordLength -MaxPasswordAge \"10675199.00:00:00\"\n    error_action: stop\n    parameters:\n      LockoutThreshold: \"{{try_before_lock}}\"\n      MinPasswordLength: \"{{pass_length}}\"\n      LockoutDuration: \"{{lock_duration}}\"\n      LockoutObservationWindow: \"{{lock_observation}}\"\n      ComplexityEnabled: \"{{complexity}}\""
  },
  {
    "path": "ansible/roles/ps/tasks/main.yml",
    "content": "- name: Play task {{ps_script}}\n  script: \"{{ps_script}}\""
  },
  {
    "path": "ansible/roles/sccm/config/accounts/tasks/main.yml",
    "content": "- name: Create CMA Accounts\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $siteCode,\n\n          [String]\n          $sccmFQDN,\n\n          [String]\n          $username,\n\n          [String]\n          $password\n      )\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n\n      $account = Get-CMAccount -UserName $username\n      if ($null -eq $account){\n        $securePass = ConvertTo-SecureString -String $password -AsPlainText -Force\n        New-CMAccount -UserName $username -Password $securePass -SiteCode $siteCode\n        $Ansible.Changed = $true\n      } else {\n        $Ansible.Changed = $false\n      }\n    parameters:\n      siteCode: \"{{site_code}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n      username: \"{{item.value.name}}\"\n      password: \"{{item.value.password}}\"\n  with_dict: \"{{ cma_users }}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\""
  },
  {
    "path": "ansible/roles/sccm/config/boundary/library/sccm_boundary.ps1",
    "content": "#!powershell\n\n#Requires -Module Ansible.ModuleUtils.Legacy\n\n# https://learn.microsoft.com/en-us/powershell/module/configurationmanager/new-cmboundary\n# sccm_boundary:\n#   name: \"boundary name\"\n#   type: IPSubNet/ADSite/IPv6Prefix/IPRange/VPN\n#   value: \"value\" (ex: \"172.16.50.0/24\" / \"Default-First-Site-Name\" / \"10.255.255.0-10.255.255.255\")\n#   site_code: \"code\"\n#   state: \"present\" (absent/present)\n\n$ErrorActionPreference = \"Stop\"\n$ProgressPreference = \"SilentlyContinue\"\n\n$params = Parse-Args -arguments $args -supports_check_mode $true\n$check_mode = Get-AnsibleParam -obj $params -name \"_ansible_check_mode\" -type \"bool\" -default $false\n\n$name = Get-AnsibleParam -obj $params -name \"name\" -type \"str\" -failifempty $true\n$boundary_type = Get-AnsibleParam -obj $params -name \"type\" -type \"str\" -failifempty $true -validateset \"IPSubNet\",\"ADSite\" ,\"IPv6Prefix\",\"IPRange\",\"VPN\"\n$boundary_value = Get-AnsibleParam -obj $params -name \"value\" -type \"str\" -failifempty $true\n$siteCode = Get-AnsibleParam -obj $params -name \"site_code\" -type \"str\" -failifempty $true\n$state = Get-AnsibleParam -obj $params -name \"state\" -type \"str\" -default \"present\" -validateset \"absent\", \"present\"\n$server = Get-AnsibleParam -obj $params -name \"server\" -type \"str\" -failifempty $true\n\n$result = @{\n    changed = $false\n}\n\nImport-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n$sc = Get-PSDrive -PSProvider CMSITE\nif ($null -eq $sc) {\n    New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $server -Description \"primary site\"\n}\nSet-Location ($siteCode +\":\")\n\n# search by name\n($boundary = Get-CMBoundary -BoundaryName $name) | out-null\n\nif ($state -eq \"absent\" -and $null -ne $boundary) {\n    $boundary | Remove-CMBoundary -WhatIf:$check_mode | out-null\n    $result.changed = $true\n} elseif ($state -eq \"present\") {\n    $update = $true\n    if ($null -eq $boundary) {\n        try {\n            New-CMBoundary -DisplayName $name -BoundaryType $boundary_type -Value $boundary_value -WhatIf:$check_mode | out-null\n        } catch {\n            Set-CMBoundary -DisplayName $name -BoundaryType $boundary_type -Value $boundary_value -WhatIf:$check_mode | out-null\n        }\n        $result.changed = $true\n    }\n}\n\nExit-Json -obj $result"
  },
  {
    "path": "ansible/roles/sccm/config/boundary/library/sccm_boundary_group.ps1",
    "content": "#!powershell\n\n#Requires -Module Ansible.ModuleUtils.Legacy\n\n# https://learn.microsoft.com/en-us/powershell/module/configurationmanager/new-cmboundary\n# sccm_boundary_group:\n#   name: \"boundary group name\"\n#   server: sccmserver.myad.lab\n#   site_code: \"code\"\n#   state: \"present\" (absent/present)\n\n$ErrorActionPreference = \"Stop\"\n$ProgressPreference = \"SilentlyContinue\"\n\n$params = Parse-Args -arguments $args -supports_check_mode $true\n$check_mode = Get-AnsibleParam -obj $params -name \"_ansible_check_mode\" -type \"bool\" -default $false\n\n$name = Get-AnsibleParam -obj $params -name \"name\" -type \"str\" -failifempty $true\n$server = Get-AnsibleParam -obj $params -name \"server\" -type \"str\" -failifempty $true\n$siteCode = Get-AnsibleParam -obj $params -name \"site_code\" -type \"str\" -failifempty $true\n$state = Get-AnsibleParam -obj $params -name \"state\" -type \"str\" -default \"present\" -validateset \"absent\", \"present\"\n\n$result = @{\n    changed = $false\n}\n\nImport-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n$sc = Get-PSDrive -PSProvider CMSITE\nif ($null -eq $sc) {\n    New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $server -Description \"primary site\"\n}\nSet-Location ($siteCode +\":\")\n\n($boundaryGroup = Get-CMBoundaryGroup -Name $name) | out-null\n\nif ($state -eq \"absent\" -and $null -ne $boundaryGroup) {\n    $boundaryGroup | Remove-CMBoundaryGroup -WhatIf:$check_mode | out-null\n    $result.changed = $true\n} elseif ($state -eq \"present\") {\n    if ($null -eq $boundaryGroup) {\n        try {\n            New-CMBoundaryGroup -Name $name -AddSiteSystemServerName $server -DefaultSiteCode $sitecode -WhatIf:$check_mode | out-null\n        } catch {\n            Set-CMBoundaryGroup -Name $name -AddSiteSystemServerName $server -DefaultSiteCode $sitecode -WhatIf:$check_mode | out-null\n        }\n        $result.changed = $true\n    }\n}\n\n\nExit-Json -obj $result"
  },
  {
    "path": "ansible/roles/sccm/config/boundary/library/sccm_boundary_to_boundarygroup.ps1",
    "content": "#!powershell\n\n#Requires -Module Ansible.ModuleUtils.Legacy\n\n# https://learn.microsoft.com/en-us/powershell/module/configurationmanager/new-cmboundary\n#  sccm_boundary_to_boundarygroup:\n#   boundary_name: \"boundary name\"\n#   boundary_group: \"boundary group name\"\n#   site_code: \"code\"\n#   state: \"present\" (absent/present)\n\n$ErrorActionPreference = \"Stop\"\n$ProgressPreference = \"SilentlyContinue\"\n\n$params = Parse-Args -arguments $args -supports_check_mode $true\n$check_mode = Get-AnsibleParam -obj $params -name \"_ansible_check_mode\" -type \"bool\" -default $false\n\n$boundaryName = Get-AnsibleParam -obj $params -name \"boundary_name\" -type \"str\" -failifempty $true\n$boundaryGroupName = Get-AnsibleParam -obj $params -name \"boundary_group\" -type \"str\" -failifempty $true\n$siteCode = Get-AnsibleParam -obj $params -name \"site_code\" -type \"str\" -failifempty $true\n$state = Get-AnsibleParam -obj $params -name \"state\" -type \"str\" -default \"present\" -validateset \"absent\", \"present\"\n$server = Get-AnsibleParam -obj $params -name \"server\" -type \"str\" -failifempty $true\n\n$result = @{\n    changed = $false\n}\n\nImport-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n$sc = Get-PSDrive -PSProvider CMSITE\nif ($null -eq $sc) {\n    New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $server -Description \"primary site\"\n}\nSet-Location ($siteCode +\":\")\n\n($boundary_group_list = Get-CMBoundary -BoundaryGroupName $boundaryGroupName) | out-null\n\n($boundary = Get-CMBoundary -BoundaryName $boundaryName) | out-null \n($boundaryGroup = Get-CMBoundaryGroup -Name $boundaryGroupName) | out-null\n\n$present = $false\nforeach  ($b in $boundary_group_list){\n    if ($b.DisplayName -eq $boundary.DisplayName){\n        $present = $true\n        break\n    }\n}\n\nif ($state -eq \"absent\" -and $present) {\n    $boundaryGroup | Remove-CMBoundaryFromGroup -BoundaryName $boundaryName -WhatIf:$check_mode | out-null\n    $result.changed = $true\n} elseif ($state -eq \"present\") {\n    if (-Not $present) {\n        try {\n            Add-CMBoundaryToGroup -BoundaryName $boundaryName -BoundaryGroupName $boundaryGroupName -WhatIf:$check_mode | out-null\n            $result.changed = $true\n        } catch {\n            $result.changed = $false\n        }\n    }\n}\n\n\nExit-Json -obj $result"
  },
  {
    "path": "ansible/roles/sccm/config/boundary/tasks/main.yml",
    "content": "- name: Create boundary\n  sccm_boundary:\n    name: \"ADSiteBoundary01\"\n    type: \"ADSite\"\n    value: \"Default-First-Site-Name\"\n    site_code: \"{{site_code}}\"\n    server: \"{{sccm_server}}.{{domain}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n    ansible_become_flags: logon_flags=\n\n- name: Create boundary group\n  sccm_boundary_group:\n    name: \"BoundaryGroup01\"\n    server: \"{{sccm_server}}.{{domain}}\"\n    site_code: \"{{site_code}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n    ansible_become_flags: logon_flags=\n\n- name: Add boundary to boundary group\n  sccm_boundary_to_boundarygroup:\n    boundary_name: \"ADSiteBoundary01\"\n    boundary_group: \"BoundaryGroup01\"\n    site_code: \"{{site_code}}\"\n    server: \"{{sccm_server}}.{{domain}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n    ansible_become_flags: logon_flags=\n"
  },
  {
    "path": "ansible/roles/sccm/config/client_install/tasks/main.yml",
    "content": "- name: Install client\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $siteCode,\n\n          [String]\n          $sccmFQDN,\n\n          [String]\n          $device\n      )\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n\n      $Ansible.Changed = $false\n      $client_active = Get-CMDevice| Select-Object Name, ClientActiveStatus\n      foreach($c in $client_active) {\n          if (($c.name -eq $device) -and (-not $c.ClientActiveStatus)) {\n            Install-CMClient -DeviceName $device -SiteCode $siteCode -AlwaysInstallClient $True -IncludeDomainController $true\n            $Ansible.Changed = $true\n          }\n      }\n    parameters:\n      siteCode: \"{{site_code}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n      device: \"{{item}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  loop: \"{{clients}}\"\n"
  },
  {
    "path": "ansible/roles/sccm/config/client_push/tasks/main.yml",
    "content": "# script source : https://github.com/MicrosoftDocs/sccm-docs-powershell-ref/blob/main/sccm-ps/ConfigurationManager/Set-CMClientPushInstallation.md\n- name: Create Configuration For client push\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $siteCode,\n\n          [String]\n          $sccmFQDN,\n\n          [String]\n          $pushAccount\n      )\n      # Step 1 - Import the Configuration Manager module\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n      $property = \"SMSSITECODE=\" + $siteCode\n\n      Set-CMClientPushInstallation `\n      -SiteCode $siteCode `\n      -EnableAutomaticClientPushInstallation $True `\n      -EnableSystemTypeConfigurationManager $True `\n      -EnableSystemTypeServer $True `\n      -AllownNTLMFallback $True `\n      -EnableSystemTypeWorkstation $True `\n      -InstallClientToDomainController $false `\n      -AddAccount $pushAccount `\n      -InstallationProperty $property\n    parameters:\n      siteCode: \"{{site_code}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n      pushAccount: \"{{push_account}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n"
  },
  {
    "path": "ansible/roles/sccm/config/discovery/tasks/main.yml",
    "content": "- name: Restart service SMS_SITE_COMPONENT_MANAGER\n  win_service:\n    name: 'SMS_SITE_COMPONENT_MANAGER'\n    force_dependent_services: yes\n    state: restarted\n\n# https://dexterposh.blogspot.com/2014/02/powershell-sccm-2012-r2-discovery.html\n# https://support.microsoft.com/en-us/topic/windows-powershell-changes-in-cumulative-update-4-for-system-center-2012-r2-configuration-manager-da42afbb-f286-edcf-5f1d-3dec46f415d3\n- name: Setup discovery\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $siteCode,\n\n          [String]\n          $sccmFQDN,\n\n          [String]\n          $group_ldap,\n          \n          [String]\n          $computer\n      )\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n\n      # Forest\n      # create a Schedule Token \n      $Schedule = New-CMSchedule -RecurInterval Days -RecurCount 7\n      \n      # Enable the Active Directory Forest Discovery \n      try {\n        Set-CMDiscoveryMethod -ActiveDirectoryForestDiscovery -SiteCode $siteCode -Enabled:$true -PollingSchedule $Schedule -EnableActiveDirectorySiteBoundaryCreation:$true -EnableSubnetBoundaryCreation:$true\n      } catch {\n        # already exist\n        $Ansible.Changed = $false\n      }\n\n      # To run AD Forest Discovery now\n      Invoke-CMForestDiscovery -SiteCode $siteCode -Verbose\n\n      # Group\n      try {\n        Set-CMDiscoveryMethod -SiteCode $siteCode `\n        -ActiveDirectoryGroupDiscovery -Enabled $true `\n        -EnableDeltaDiscovery $true -DeltaDiscoveryIntervalMinutes 5 `\n        -EnableFilteringExpiredLogon $true -TimeSinceLastLogonDays 90 `\n        -EnableFilteringExpiredPassword $true -TimeSinceLastPasswordUpdateDays 90 `\n        -DiscoverDistributionGroupsMembership $true `\n        -AddGroupDiscoveryScope (New-CMADGroupDiscoveryScope `\n            -name MyScope -SiteCode $siteCode -LdapLocation $group_ldap -RecursiveSearch $true)\n      } catch {\n        # already exist\n        $Ansible.Changed = $false\n      }\n      # need to restart the Component Manager Service ..to reflect the changes\n      (Get-Service SMS_SITE_COMPONENT_MANAGER -ComputerName $computer).stop()\n\n      Start-Sleep -Seconds 10\n\n      (Get-Service SMS_SITE_COMPONENT_MANAGER -ComputerName $computer).start()\n\n      # To run Group Discovery now\n      Invoke-CMForestDiscovery -SiteCode $siteCode -Verbose\n    error_action: stop\n    parameters:\n      siteCode: \"{{site_code}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n      group_ldap: \"LDAP://CN=SCCM-Managed-Device,CN=USERS,DC=sccm,DC=lab\"\n      computer: \"MECM\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\""
  },
  {
    "path": "ansible/roles/sccm/config/naa/tasks/main.yml",
    "content": "# script source : https://www.oscc.be/sccm/configmgr/powershell/naa/Set-NAA-using-Powershell-in-CB/\n# error on first try :/\n# \"The property 'Values' cannot be found on this object. Verify that the property exists and can be set.\",\n- name: Create Configuration Manager user account \n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param ( \n          [String]\n          $siteCode,\n\n          [String]\n          $sccmFQDN,\n\n          [String]\n          $user\n      )\n      # Step 1 - Import the Configuration Manager module\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n\n      # Step 2 - make the user account your new Network Access Account\n      $component = gwmi -class SMS_SCI_ClientComp -Namespace \"root\\sms\\site_$($siteCode)\"  | Where-Object {$_.ItemName -eq \"Software Distribution\"}\n      $props = $component.PropLists\n\n      if ($null -eq $props) {\n        $new = [WmiClass] \"root\\sms\\site_$($siteCode):SMS_EmbeddedPropertyList\"\n        $embeddedproperylist = $new.CreateInstance()\n        $embeddedproperylist.PropertyListName = \"Network Access User Names\"\n        $props = @($embeddedproperylist)\n      }\n\n      $prop = $props | where {$_.PropertyListName -eq \"Network Access User Names\"}\n      $prop.Values = $user\n\n      $component.PropLists = $props\n      $component.Put() | Out-Null\n    parameters:\n      siteCode: \"{{site_code}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n      user: \"{{naa_user}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n"
  },
  {
    "path": "ansible/roles/sccm/config/pxe/tasks/main.yml",
    "content": "# https://www.prajwaldesai.com/install-sccm-distribution-point-using-powershell-script/\n- name: Create PXE config \n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $siteCode,\n\n          [String]\n          $sccmFQDN,\n\n          [String]\n          $pass\n      )\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n\n      #Define PXE Password\n      $PXEpass = convertto-securestring -string $pass -asplaintext -force\n      # get distribution point\n      $DP = Get-CMDistributionPoint -SiteCode $siteCode\n      # Enable PXE with password\n      # Set-CMDistributionPoint -InputObject $DP -EnablePxe $True -PXEpassword $PXEpass -AllowPxeResponse $True -EnableUnknownComputerSupport $True \n      # without password\n      Set-CMDistributionPoint -InputObject $DP -EnablePxe $True -AllowPxeResponse $True -EnableUnknownComputerSupport $True \n      #Enable Multicast Feature\n      # Add-CMMulticastServicePoint -SiteSystemServerName $DP -SiteCode $siteCode\n    parameters:\n      siteCode: \"{{site_code}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n      pass: \"{{pxe_pass}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\""
  },
  {
    "path": "ansible/roles/sccm/config/users/tasks/main.yml",
    "content": "- name: Add full administrators accounts\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $siteCode,\n\n          [String]\n          $sccmFQDN,\n\n          [String]\n          $username\n      )\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n\n      $account = Get-CMAdministrativeUser -Name $username\n      if ($null -eq $account){\n        New-CMAdministrativeUser -Name $username -RoleName \"Full Administrator\"\n        $Ansible.Changed = $true\n      } else {\n        $Ansible.Changed = $false\n      }\n    parameters:\n      siteCode: \"{{site_code}}\"\n      username: \"{{item}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  loop: \"{{ admins }}\""
  },
  {
    "path": "ansible/roles/sccm/install/adk/tasks/main.yml",
    "content": "# Step 7 – Installing Windows ADK version 2004\n# --------------------------------------------------------------\n\n- name: create directory to store the install files\n  ansible.windows.win_file:\n    path: C:\\setup\n    state: directory\n\n- name: create directory to store the install files\n  ansible.windows.win_file:\n    path: C:\\setup\\adk\n    state: directory\n\n- name: check ADK version 2004 installation exists\n  win_stat:\n    path: C:\\setup\\adk\\adksetup.exe\n  register: adksetup_installer_file\n\n# Must be ADK version 2004 for MECM 2303\n# Check if the file has already been downloaded (?)\n- name: download ADK version 2004\n  ansible.windows.win_get_url:\n    url: https://go.microsoft.com/fwlink/?linkid=2120254\n    dest: C:\\setup\\adk\\adksetup.exe\n  when: not adksetup_installer_file.stat.exists\n\n- name: check ADK adkwinpesetup exists\n  win_stat:\n    path: C:\\setup\\adk\\adkwinpesetup.exe\n  register: adkwinpesetup_installer_file\n\n- name: download PE add-on\n  ansible.windows.win_get_url:\n    url: https://go.microsoft.com/fwlink/?linkid=2120253\n    dest: C:\\setup\\adk\\adkwinpesetup.exe\n  when: not adkwinpesetup_installer_file.stat.exists\n\n- name: installing ADK version 2004\n  win_shell: .\\adksetup.exe /quiet /features OptionId.DeploymentTools OptionId.UserStateMigrationTool\n  args:\n    chdir: C:\\setup\\adk \n\n- name: installing PE add-on\n  win_shell: .\\adkwinpesetup.exe /quiet /features OptionId.WindowsPreinstallationEnvironment\n  args:\n    chdir: C:\\setup\\adk"
  },
  {
    "path": "ansible/roles/sccm/install/iis/tasks/main.yml",
    "content": "# Step 6 – Install Web Server IIS (Prerequisites)\n# --------------------------------------------------------------\n\n- name: create directory to store the install files\n  ansible.windows.win_file:\n    path: C:\\setup\n    state: directory\n\n- name: create directory to store the install files\n  ansible.windows.win_file:\n    path: C:\\setup\\net3.5\n    state: directory\n\n- name: install features Remote Differential Compression feature and BITS\n  win_feature:\n    name: \n      - RDC\n      - BITS\n  register: win_feature\n\n- name: Reboot if installing windows feature requires it\n  ansible.windows.win_reboot:\n  when: win_feature.reboot_required\n\n- name: Enable update service\n  ansible.windows.win_service:\n    name: Windows Update\n    state: started\n    start_mode: auto\n\n- name: install .NET Framework 3.5 with DISM\n  win_shell: DISM /Online /Enable-Feature /FeatureName:NetFx3 /All\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n\n- name: install IIS feature and other components\n  win_feature:\n    name:\n      - Web-Server\n      - Web-Dyn-Compression\n      - Web-Http-Redirect\n      - Web-Log-Libraries\n      - Web-Request-Monitor\n      - Web-Http-Tracing\n      - Web-Windows-Auth\n      - Web-App-Dev\n      - Web-Net-Ext\n      - Web-Net-Ext45\n      - Web-Asp-Net\n      - Web-Asp-Net45\n      - Web-Mgmt-Tools\n      - Web-Mgmt-Compat\n      - Web-WMI\n  register: win_feature_iis\n\n- name: Reboot if installing windows feature requires it\n  ansible.windows.win_reboot:\n  when: win_feature_iis.reboot_required\n"
  },
  {
    "path": "ansible/roles/sccm/install/mecm/files/ConfigMgrAutoSave.ini",
    "content": "[Identification]\nAction=InstallPrimarySite\n\n\n[Options]\nProductID=EVAL\nSiteCode=\"{{site_code}}\"\nSiteName=\"{{domain}} Site\"\nSMSInstallDir=C:\\Program Files\\Microsoft Configuration Manager\nSDKServer=\"{{sccm_server}}.{{domain}}\"\nRoleCommunicationProtocol=HTTPorHTTPS\nClientsUsePKICertificate=0\nPrerequisiteComp=0\nPrerequisitePath=C:\\updates\nManagementPoint=\"{{sccm_server}}.{{domain}}\"\nManagementPointProtocol=HTTP\nDistributionPoint=\"{{sccm_server}}.{{domain}}\"\nDistributionPointProtocol=HTTP\nDistributionPointInstallIIS=0\nAdminConsole=1\nJoinCEIP=0\n\n[SQLConfigOptions]\nSQLServerName=\"{{sccm_mssql_server}}.{{domain}}\"\nDatabaseName=CM_P01\nSQLSSBPort=4022\n\n[CloudConnectorOptions]\nCloudConnector=1\nCloudConnectorServer=\"{{sccm_server}}.{{domain}}\"\nUseProxy=0\nProxyName=\nProxyPort=\n\n[SystemCenterOptions]\nSysCenterId=TPy9JI2owGLVpOdtunFRk8tF5Kitq5kmIYHrbBm+pIU=\n\n[HierarchyExpansionOption]\n"
  },
  {
    "path": "ansible/roles/sccm/install/mecm/tasks/main.yml",
    "content": "- name: create directory to store the downloaded prerequisite files\n  ansible.windows.win_file:\n    path: C:\\setup\n    state: directory\n\n- name: Download Visual C++ 2017 Redistributable\n  ansible.windows.win_get_url:\n    url: https://aka.ms/vs/15/release/vc_redist.x64.exe\n    dest: C:\\setup\\vc_redist.x64.exe\n  register: download_vc_redist\n\n- name: Install Visual C++ 2017 Redistributable\n  ansible.windows.win_package:\n    path: C:\\setup\\vc_redist.x64.exe\n    arguments: /quiet /norestart\n  when: download_vc_redist.changed\n\n- name: Install ODBC Mssql 18 driver\n  ansible.windows.win_package:\n    arguments: \"IACCEPTMSODBCSQLLICENSETERMS=YES ALLUSERS=1\"\n    path: https://go.microsoft.com/fwlink/?linkid=2266640&clcid=0x409&culture=en-us&country=us\n    state: present\n    creates_path: \"%ProgramFiles%\\\\Microsoft SQL Server\\\\Client SDK\\\\ODBC\"\n  register: odbc_install\n  until: odbc_install is success\n  retries: 3  # Try 3 times just in case it failed to download the URL\n  delay: 1\n\n- name: reboot after installing ODBC if required\n  ansible.windows.win_reboot:\n  when: odbc_install.reboot_required\n\n# Step 14 – Download SCCM 1902 Baseline Media\n# --------------------------------------------------------------\n\n- name: create directory to store the downloaded prerequisite files\n  ansible.windows.win_file:\n    path: C:\\setup\n    state: directory\n\n- name: MECM installation media exists\n  win_stat:\n    path: C:\\setup\\MCM_Configmgr_2303.exe\n  register: mecm_installer_file\n\n- name: download MECM installation media\n  ansible.windows.win_get_url:\n    url: https://go.microsoft.com/fwlink/p/?LinkID=2195628&clcid=0x409&culture=en-us&country=us\n    dest: C:\\setup\\MCM_Configmgr_2303.exe\n  when: not mecm_installer_file.stat.exists\n\n- name: Remove directory cd.retail.LN if exist\n  ansible.windows.win_file:\n    path: C:\\setup\\cd.retail.LN\n    state: absent\n  ignore_errors: true\n\n# We should verify if the cd.retail.LN directory exists first.\n# If yes, remove it.\n- name: extract MECM installation media\n  win_shell: .\\MCM_Configmgr_2303.exe -s\n  args:\n    chdir: C:\\setup\\\n\n#- name: move the MECM installation media to C:\\\n#  ansible.windows.win_powershell:\n#    script: Move-Item -Path C:\\Windows\\Temp\\cd.retail.LN -Destination C:\\\n\n- name: create directory to store the downloaded prerequisite files\n  ansible.windows.win_file:\n    path: C:\\updates\n    state: directory\n\n- name: download prerequisite files\n  win_shell: .\\setupdl.exe /NoUI C:\\updates\n  args:\n    chdir: C:\\setup\\cd.retail.LN\\SMSSETUP\\BIN\\X64\n\n# Step 15 – Install SCCM 1902 using Baseline Media\n# --------------------------------------------------------------\n\n- name: copy the configuration file\n  win_template:\n    src: files/ConfigMgrAutoSave.ini\n    dest: C:\\setup\\ConfigMgrAutoSave.ini\n\n- name: Fix MSSQL generate certificate issue (change crypto rsa permissions)\n  ansible.windows.win_acl:\n    path: C:\\ProgramData\\Microsoft\\Crypto\\RSA\n    user: Administrators\n    rights: FullControl\n    type: allow\n    state: present\n    inherit: ContainerInherit, ObjectInherit\n    propagation: 'InheritOnly'\n\n- name: install MECM (this one take an eternity ~ 1 hour  )\n  win_shell: .\\setup.exe /SCRIPT \"C:\\setup\\ConfigMgrAutoSave.ini\"\n  args:\n    chdir: C:\\setup\\cd.retail.LN\\SMSSETUP\\BIN\\X64\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    domain_name: \"{{domain}}\"\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n"
  },
  {
    "path": "ansible/roles/sccm/install/prerequistes/tasks/main.yml",
    "content": "# Step 3 - Creating the System Management Container\n# --------------------------------------------------------------\n\n- name: create the System Management Container\n  ansible.windows.win_powershell:\n    script: |\n      $systemDN = \"CN=System,\" + (Get-ADDomain).DistinguishedName\n      New-ADObject -Type container -Name \"System Management\" -Path $systemDN\n\n# Step 4 - Grant SCCM Server Permissions on System Management Container\n# --------------------------------------------------------------\n\n# Not children inherited (is it bad?)\n# SRV01 is hardcoded\n- name: create the System Management Container\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $SCCMServer\n      )\n      $systemMgmtDN = \"CN=System Management,CN=System,\" + (Get-ADDomain).DistinguishedName\n      $acl = Get-ACL -Path \"AD:\\$systemMgmtDN\"\n      $sccmIdentity = Get-ADComputer -Identity $SCCMServer\n      $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $sccmIdentity.SID, \"GenericAll\", \"Allow\"\n      $acl.AddAccessRule($ace)\n      Set-ACL -Path \"AD:\\$systemMgmtDN\" -AclObject $acl\n    parameters:\n      SCCMServer: \"{{sccm_server}}\"\n\n# Step 5 – Extending Active Directory Schema\n# --------------------------------------------------------------\n\n- name: create directory to store the downloaded prerequisite files\n  ansible.windows.win_file:\n    path: C:\\setup\n    state: directory\n\n# Must be run as a member of the Schema Admins security group (we'll go with a domain administrator)\n# Check if the file has already been downloaded (?)\n- name: check MECM installation media exists\n  win_stat:\n    path: C:\\setup\\MCM_Configmgr_2303.exe\n  register: mecm_installer_file\n\n- name: download MECM installation media\n  ansible.windows.win_get_url:\n    url: https://go.microsoft.com/fwlink/p/?LinkID=2195628&clcid=0x409&culture=en-us&country=us\n    dest: C:\\setup\\MCM_Configmgr_2303.exe\n  when: not mecm_installer_file.stat.exists\n\n- name: Remove directory if exist\n  ansible.windows.win_file:\n    path: C:\\setup\\cd.retail.LN\n    state: absent\n\n- name: extract MECM installation media\n  win_shell: .\\MCM_Configmgr_2303.exe -s\n  args:\n    chdir: C:\\setup\n\n#- name: move the MECM installation media to C:\\\n#  ansible.windows.win_powershell:\n#    script: Move-Item -Path C:\\Windows\\Temp\\cd.retail.LN -Destination C:\\\n\n- name: launching the Active Directory schema extension\n  win_shell: .\\extadsch.exe\n  args:\n    chdir: C:\\setup\\cd.retail.LN\\SMSSETUP\\BIN\\X64\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    domain_name: \"{{domain}}\"\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n"
  },
  {
    "path": "ansible/roles/sccm/install/wsus/tasks/main.yml",
    "content": "# Step 11 – Install WSUS Role\n# --------------------------------------------------------------\n\n- name: install WSUS\n  win_feature:\n    name:\n      - UpdateServices-Services\n      - UpdateServices-DB\n    include_management_tools: yes\n  register: wsus_install_result\n\n- name: \"Reboot and wait for the AD system to restart\"\n  win_reboot:\n    reboot_timeout: 900\n    post_reboot_delay: 100\n  when: wsus_install_result.changed\n\n- name: create directory to store updates\n  ansible.windows.win_file:\n    path: C:\\sources\\WSUS\n    state: directory\n\n# %COMPUTERNAME% won't work. Neither $env:computername.\n# So, I put a hardcoded server name for now.\n- name: WSUS Post-installation (setup the link with the SQL Server database and a directory to store updates)\n  win_shell: .\\wsusutil.exe PostInstall SQL_INSTANCE_NAME={{sccm_mssql_server}} CONTENT_DIR=C:\\sources\\WSUS\n  args:\n    chdir: C:\\Program Files\\Update Services\\Tools\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    domain_name: \"{{domain}}\"\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\""
  },
  {
    "path": "ansible/roles/sccm/pxe/defaults/main.yml",
    "content": "win10_iso_url: \"https://software-static.download.prss.microsoft.com/dbazure/988969d5-f34g-4e03-ac9d-1f9786c66750/19045.2006.220908-0225.22h2_release_svc_refresh_CLIENTENTERPRISEEVAL_OEMRET_x64FRE_en-us.iso\""
  },
  {
    "path": "ansible/roles/sccm/pxe/tasks/main.yml",
    "content": "# Download win10 iso\n- name: check downloaded iso file exists\n  win_stat:\n    path: c:\\setup\\win_10_22h2.iso\n  register: iso_file\n\n- name: check wim file exists\n  win_stat:\n    path: c:\\share_iso\\install.wim\n  register: wim_file\n\n- name: download win10 iso file (~ 5.4GB )\n  win_get_url:\n      url: \"{{win10_iso_url}}\"\n      dest: 'c:\\setup\\win_10_22h2.iso'\n  when: not (iso_file.stat.exists or wim_file.stat.exists)\n\n- name: create share folder\n  win_file:\n    path: C:\\share_iso\n    state: directory\n\n- name: Ensure share exists\n  win_share:\n    name: share_iso\n    description: iso share for all domain users\n    path: C:\\share_iso\n    list: yes\n    full: Administrators\n    change: Users\n\n- name: check wim file exists\n  win_stat:\n    path: c:\\share_iso\\install.wim\n  register: wim_file\n\n# Extract setup.wim from iso\n- name: open ISO and extract wim file\n  ansible.windows.win_powershell:\n    script: |\n      $mountResult = Mount-DiskImage -ImagePath \"c:\\setup\\win_10_22h2.iso\" \n      $driveLetter = ($mountResult | Get-Volume).DriveLetter\n      copy \"${driveLetter}:\\sources\\install.wim\" \"c:\\share_iso\\install.wim\"\n      Dismount-DiskImage -ImagePath \"c:\\setup\\win_10_22h2.iso\"\n      rm c:\\setup\\win_10_22h2.iso\n  when: not wim_file.stat.exists\n\n# Install operating system image\n- name: Create Operating system image\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $siteCode,\n\n          [String]\n          $sccmFQDN,\n\n          [String]\n          $shareServer\n      )\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n\n      $opsys = Get-CMOperatingSystemImage -Name \"Windows_10_22h2\"\n      if ($null -eq $opsys){\n        $image = New-CMOperatingSystemImage -Name \"Windows_10_22h2\" -Path \"\\\\${shareServer}\\share_iso\\install.wim\"\n        $Ansible.Changed = $true\n      } else {\n        $Ansible.Changed = $false\n      }\n    parameters:\n      siteCode: \"{{site_code}}\"\n      shareServer: \"{{sccm_server}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n\n# Create task sequence\n- name: Create Task sequence\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $domainName,\n\n          [String]\n          $sccmFQDN,\n\n          [String]\n          $domainAccount,\n\n          [String]\n          $domainPassword,\n\n          [String]\n          $ou,\n\n          [String]\n          $siteCode,\n\n          [String]\n          $shareServer,\n\n          [String]\n          $adminPass\n      )\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n      $name = \"Install_win10_OS_image\"\n\n      $ts = Get-CMTaskSequence -name $name\n\n      if ($null -eq $ts){\n        # operating system\n        $operating_system_image = Get-CMOperatingSystemImage -Name \"Windows_10_22h2\"\n        # boot image\n        $boot_image = Get-CMBootImage -name \"Boot image (x64)\"\n\n        # admin pass\n        $adminpass_secure = convertto-securestring -string $adminPass -asplaintext -force\n\n        # client package\n        $cp = Get-CMPackage -name \"Configuration Manager Client Package\"\n        \n        $parameters = @{\n          InstallOperatingSystemImage = $true\n          Name = $name\n          Description = \"NewInstallOSImage parameter set\"\n          BootImagePackageId = $boot_image.PackageID\n          HighPerformance = $true\n          CaptureNetworkSetting = $true\n          CaptureUserSetting = $false\n          SaveLocally = $true\n          CaptureLocallyUsingLink = $true\n          CaptureWindowsSetting = $true\n          ConfigureBitLocker = $false\n          PartitionAndFormatTarget = $true\n          ApplyAll = $false\n          OperatingSystemImagePackageId = $operating_system_image.PackageID\n          OperatingSystemImageIndex = 1\n          GeneratePassword = $false\n          LocalAdminPassword = $adminpass_secure\n          JoinDomain = \"DomainType\"\n          DomainAccount = $domainAccount\n          DomainName = $domainName\n          DomainOrganizationUnit = $ou\n          DomainPassword = ConvertTo-SecureString -String $domainPassword -AsPlainText -Force\n          ClientPackagePackageId = $cp.PackageID\n          IgnoreInvalidApplication = $false\n          SoftwareUpdateStyle = \"NoInstall\"\n        }\n\n        New-CMTaskSequence @parameters\n        $Ansible.Changed = $true\n      } else {\n        $Ansible.Changed = $false\n      }\n    parameters:\n      siteCode: \"{{site_code}}\"\n      shareServer: \"{{sccm_server}}\"\n      adminPass: \"{{admin_pass}}\"\n      domainName : \"{{domain}}\"\n      ou: \"{{ou_location}}\"\n      domainAccount: \"{{naa_user}}\"\n      domainPassword: \"{{naa_pass}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n\n# start distribute content\n- name: Start distribute content\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $siteCode,\n\n          [String]\n          $sccmFQDN,\n\n          [String]\n          $distributionPoint\n      )\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n\n      # distribute operating system image\n      Start-CMContentDistribution -BootImageName \"Boot image (x64)\" -DistributionPointName $distributionPoint\n      Start-CMContentDistribution -BootImageName \"Boot image (x86)\" -DistributionPointName $distributionPoint\n      # distribute boot image\n      Start-CMContentDistribution -OperatingSystemImageName \"Windows_10_22h2\" -DistributionPointName $distributionPoint\n\n      # distribute Configuration manager client package\n      $package = Get-CMDeploymentPackage -DeploymentPackageName \"Configuration Manager Client Package\" -DistributionPointName $distributionPoint\n      if ($null -eq $package) {\n        # package not found sleep waiting the Configuration Manager Client Package presence\n        Start-Sleep -seconds 300\n      }\n      Start-CMContentDistribution -DeploymentPackageName \"Configuration Manager Client Package\" -DistributionPointName $distributionPoint\n    parameters:\n      siteCode: \"{{site_code}}\"\n      distributionPoint: \"{{sccm_server}}.{{domain}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n\n# update unknow computers\n- name: Update unknow computers collection\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $siteCode,\n\n          [String]\n          $sccmFQDN\n      )\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n      Get-CMCollection -Name \"All Unknown Computers\" | Invoke-CMCollectionUpdate\n    parameters:\n      siteCode: \"{{site_code}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n\n# Deploy sequence\n- name: Deploy Task sequence\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $domainName,\n\n          [String]\n          $sccmFQDN,\n\n          [String]\n          $siteCode\n      )\n      Import-Module $env:SMS_ADMIN_UI_PATH.Replace(\"\\bin\\i386\",\"\\bin\\configurationmanager.psd1\") -force\n      $sc = Get-PSDrive -PSProvider CMSITE\n      if ($null -eq $sc) {\n        New-PSDrive -Name $siteCode -PSProvider \"CMSite\" -Root $sccmFQDN -Description \"primary site\"\n      }\n      Set-Location ($siteCode +\":\")\n      $ts_name = \"Install_win10_OS_image\"\n      $ts_deploy = Get-CMTaskSequenceDeployment -name \"deploy_pxe\"\n\n      $ts = Get-CMTaskSequence -name $ts_name\n      $collection = Get-CMCollection -name \"All Unknown Computers\"\n      if ($null -eq $ts_deploy){\n        # New-CMTaskSequenceDeployment\n        $parameters = @{\n          InputObject = $ts\n          CollectionId = $collection.CollectionID\n          AllowFallback = $true\n          Availability = \"MediaAndPxe\"\n          InternetOption = $false\n          RunFromSoftwareCenter = $true\n          SoftwareInstallation = $true\n          SystemRestart = $true\n          UseMeteredNetwork = $false\n          PersistOnWriteFilterDevice = $true\n          ShowTaskSequenceProgress = $true\n        }\n        New-CMTaskSequenceDeployment @parameters\n        $Ansible.Changed = $true\n      } else {\n        $Ansible.Changed = $false\n      }\n    parameters:\n      siteCode: \"{{site_code}}\"\n      domainName : \"{{domain}}\"\n      sccmFQDN: \"{{sccm_server}}.{{domain}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n"
  },
  {
    "path": "ansible/roles/security/account_is_sensitive/tasks/main.yml",
    "content": "- name: Account is sensitive\n  ansible.windows.win_shell: |\n    Set-ADUser -Identity \"{{item.value.account}}\" -AccountNotDelegated $true \n  with_dict: \"{{ security_vars }}\""
  },
  {
    "path": "ansible/roles/security/asr/tasks/main.yml",
    "content": "- name: Enable ASR rule\n  ansible.windows.win_shell: |\n    Add-MpPreference -AttackSurfaceReductionRules_Ids {{item.value.ruleid}} -AttackSurfaceReductionRules_Actions enable\n  with_dict: \"{{ security_vars }}\""
  },
  {
    "path": "ansible/roles/security/directory/tasks/main.yml",
    "content": "- name: Create directory\n  ansible.windows.win_file:\n    path: \"{{item.value}}\"\n    state: directory\n  with_dict: \"{{ security_vars }}\""
  },
  {
    "path": "ansible/roles/security/enable_run_as_ppl/tasks/main.yml",
    "content": "- name: Enable run as PPL\n  win_regedit:\n    path: HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa\n    name: RunAsPPL\n    data: 1\n    type: dword"
  },
  {
    "path": "ansible/roles/security/files/tasks/main.yml",
    "content": "- name: Copy a single file\n  ansible.windows.win_copy:\n    src: \"../ad/{{domain_name}}/files/{{item.value.src}}\"\n    dest: \"{{item.value.dest}}\"\n  with_dict: \"{{ security_vars }}\""
  },
  {
    "path": "ansible/roles/security/ldaps/tasks/main.yml",
    "content": "# -----------------------------\n# Import certificate into Personal store with exportable key\n# -----------------------------\n- name: Import PFX into LocalMachine\\My with exportable key\n  ansible.windows.win_shell: |\n    $pwd = ConvertTo-SecureString -String \"{{ item.value.cert_password }}\" -Force -AsPlainText\n    Import-PfxCertificate -CertStoreLocation Cert:\\LocalMachine\\My -FilePath \"{{ item.value.pfx }}\" -Password $pwd -Exportable\n  with_dict: \"{{ security_vars }}\"\n\n# -----------------------------\n# Import into Trusted Root store (for clients trusting DC)\n# -----------------------------\n- name: Import PFX into LocalMachine\\Root if not already present\n  ansible.windows.win_shell: |\n    $pwd = ConvertTo-SecureString -String \"{{ item.value.cert_password }}\" -Force -AsPlainText\n    Import-PfxCertificate -CertStoreLocation Cert:\\LocalMachine\\Root -FilePath \"{{ item.value.pfx }}\" -Password $pwd -Exportable\n  with_dict: \"{{ security_vars }}\""
  },
  {
    "path": "ansible/roles/security/maq0_client/tasks/main.yml",
    "content": "- name: Disable NTLM minimum client session security (MAQ client)\n  ansible.windows.win_regedit:\n    path: HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\MSV1_0\n    name: NtlmMinClientSec\n    type: dword\n    data: 0"
  },
  {
    "path": "ansible/roles/security/maq0_server/tasks/main.yml",
    "content": "- name: Disable NTLM minimum server session security (MAQ server)\n  ansible.windows.win_regedit:\n    path: HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\MSV1_0\n    name: NtlmMinServerSec\n    type: dword\n    data: 0"
  },
  {
    "path": "ansible/roles/security/powershell_restrict/tasks/main.yml",
    "content": "- name: Powershell Restrict\n  ansible.windows.win_shell: |\n    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope MachinePolicy -Force\n    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope UserPolicy -Force\n    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process -Force\n    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -Force\n    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Force\n  ignore_errors: true"
  },
  {
    "path": "ansible/roles/settings/adjust_rights/tasks/main.yml",
    "content": "---\n- name: Add domain users to local groups\n  win_group_membership:\n    name: \"{{item.key}}\"\n    members: \"{{ item.value }}\"\n    state: present\n  with_dict: \"{{ local_groups }}\""
  },
  {
    "path": "ansible/roles/settings/admin_password/tasks/main.yml",
    "content": "- name: Ensure that Admin is present with a valid password\n  win_user:\n    name: Administrator\n    password: \"{{local_admin_password}}\"\n    password_never_expires: yes\n    account_disabled: false\n    state: present\n\n#- name: Create administrator home directory\n#  ansible.windows.win_command: whoami\n#  vars:\n#    ansible_become: yes\n#    ansible_become_method: runas\n#    ansible_become_user: \"Administrator\"\n#    ansible_become_password: \"{{local_admin_password}}\""
  },
  {
    "path": "ansible/roles/settings/copy_files/tasks/main.yml",
    "content": "- name: Create directory\n  win_file:\n    path: C:\\tmp\n    state: directory\n\n- name: Download GOAD img in C:\\tmp\n  win_copy:\n    src: GOAD.png\n    dest: C:\\tmp\\GOAD.png\n"
  },
  {
    "path": "ansible/roles/settings/disable_nat_adapter/tasks/main.yml",
    "content": "- name: \"disable interface {{nat_adapter}}\"\n  win_shell: netsh interface set interface \"{{nat_adapter}}\" disable\n  when: two_adapters"
  },
  {
    "path": "ansible/roles/settings/enable_nat_adapter/tasks/main.yml",
    "content": "- name: \"enable interface {{nat_adapter}}\"\n  win_shell: netsh interface set interface \"{{nat_adapter}}\" enable\n  register: enable_adpter_interface\n  until: \"enable_adpter_interface is not failed\"\n  retries: 3\n  delay: 120\n  when: two_adapters"
  },
  {
    "path": "ansible/roles/settings/gpmc/tasks/main.yml",
    "content": "# https://www.ntweekly.com/2020/10/19/install-group-policy-management-tools-with-ansible/\n- name: \"Install Group Policy Management Console\"\n  win_feature:\n    name: GPMC\n    state: present\n\n"
  },
  {
    "path": "ansible/roles/settings/gpo_remove/files/remove-gpo.ps1",
    "content": "Remove-GPLink -Name \"StarkWallpaper\" -Target \"OU=North,OU=kingdoms,DC=sevenkingdoms,DC=local\" -erroraction 'silentlycontinue'\r\n\r\n#if (!(Get-ItemPropertyValue -Path \"HKCU:\\Control Panel\\Desktop\\\" -Name \"Wallpaper\")) { Set-ItemProperty -Path \"HKCU:\\Control Panel\\Desktop\" -Name Wallpaper -Value \"c:\\windows\\web\\wallpaper\\windows\\img0.jpg\"  }\r\n#\r\n\r\n$gpo_exist=Get-GPO -Name \"Remove-StarkWallpaper\" -erroraction ignore\r\nif ($gpo_exist) {\r\nRemove-GPO -Name \"Remove-StarkWallpaper\"\r\n}\r\n\r\nNew-GPO -Name \"Remove-StarkWallpaper\"-comment \"Remove StarkWallpaper\"\r\nNew-GPLink -Name \"Remove-StarkWallpaper\" -Target \"OU=North,OU=kingdoms,DC=sevenkingdoms,DC=local\"\r\n\r\nSet-GPPrefRegistryValue -Name \"Remove-StarkWallpaper\" -Context User -Action Delete -Key \"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\"\r\n\r\nSet-GPPrefRegistryValue -Name \"Remove-StarkWallpaper\" -Context User -Action Delete -Key \"HKEY_LOCAL_MACHINE\\Software\\Policies\\Microsoft\\Windows NT\\CurrentVersion\"\r\n\r\n"
  },
  {
    "path": "ansible/roles/settings/gpo_remove/tasks/main.yml",
    "content": "- name: Remove Group Policy Object \"StarkWallpaper\" to set back background image for North users\n  script: remove-gpo.ps1\n"
  },
  {
    "path": "ansible/roles/settings/hostname/tasks/main.yml",
    "content": "- name: \"Change the hostname\"\n  win_hostname:\n    name: \"{{hostname}}\"\n  register: win_hostname\n\n- name: Reboot if needed\n  win_reboot:\n    reboot_timeout: 600\n    post_reboot_delay: 30\n  when: win_hostname.reboot_required"
  },
  {
    "path": "ansible/roles/settings/keyboard/tasks/main.yml",
    "content": "#- name: \"Windows | Add the keyboard layouts\"\n#  win_shell: $langList = Get-WinUserLanguageList; $langList.Add(\"{{item}}\"); Set-WinUserLanguageList -LanguageList $langList -Force\n#  loop: \"{{layouts}}\"\n\n# taskbar\n- name: Add Keyboard Layouts registry key\n  win_regedit:\n    path:  HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\Preload\n    name: \"{{index + 1}}\"\n    data: \"{{item}}\"\n    type: string\n  loop: \"{{layouts}}\"\n  loop_control:\n    index_var: index\n\n# login screen\n- name: Add Keyboard Layouts registry key for default users\n  win_regedit:\n    path:  HKCU:\\.DEFAULT\\Keyboard Layout\\Keyboard Layouts\\Preload\n    name: \"{{index + 1}}\"\n    data: \"{{item}}\"\n    type: string\n  loop: \"{{layouts}}\"\n  loop_control:\n    index_var: index"
  },
  {
    "path": "ansible/roles/settings/no_updates/files/noupdate.ps1",
    "content": "# set the Windows Update service to \"disabled\"\nsc.exe config wuauserv start=disabled\n\n# stop the service, in case it is running\n#sc.exe stop wuauserv\n\n$ServiceName = 'wuauserv'\n$arrService = Get-Service -Name $ServiceName\nif ($arrService.Status -ne 'Stopped')\n{\n\tStop-Service $ServiceName\n}\n\n# Disable autoupdate\n#$AUSettings = (New-Object -com \"Microsoft.Update.AutoUpdate\").Settings\n#$AUSettings.NotificationLevel = 1\n#$AUSettings.Save\n\nNew-Item -Path 'HKLM:\\Software\\Policies\\Microsoft\\Windows' -Name 'WindowsUpdate' -Force\nNew-Item -Path 'HKLM:\\Software\\Policies\\Microsoft\\Windows\\WindowsUpdate' -Name 'AU' -Force\nNew-ItemProperty 'HKLM:\\Software\\Policies\\Microsoft\\Windows\\WindowsUpdate\\AU' -name 'NoAutoUpdate' -value '1' -propertyType \"DWord\" -force\n\n"
  },
  {
    "path": "ansible/roles/settings/no_updates/tasks/main.yml",
    "content": "- name: Disable windows update\n  script: noupdate.ps1"
  },
  {
    "path": "ansible/roles/settings/updates/tasks/default.yml",
    "content": "- name: Enable update service\n  ansible.windows.win_service:\n    name: Windows Update\n    state: started\n    start_mode: auto\n\n- name: Install all updates and reboot as many times as needed\n  ansible.windows.win_updates:\n    category_names: '*'\n    reboot: yes"
  },
  {
    "path": "ansible/roles/settings/user_rights/tasks/main.yml",
    "content": "# https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-rights-assignment\n# SeRemoteInteractiveLogonRight\n\n- name: Add remote desktop and administrators group to rdp\n  ansible.windows.win_user_right:\n    name: SeRemoteInteractiveLogonRight\n    users:\n    - Administrators\n    - Remote Desktop Users\n    action: set"
  },
  {
    "path": "ansible/roles/settings/windows_defender/tasks/main.yml",
    "content": "# https://answers.microsoft.com/en-us/protect/forum/protect_defender-protect_start-windows_10/how-do-i-stop-sending-antivirus-samples-to/a2e7b280-a8ba-43f5-b391-0a12c109f990\n- name: Install windows defender\n  win_feature:\n    name: Windows-Defender\n  register: win_defender_install\n\n- name: Reboot if needed\n  win_reboot:\n    reboot_timeout: 600\n    post_reboot_delay: 30\n  when: win_defender_install.reboot_required\n\n- name: Disable windows defender sending sample\n  win_shell: Set-MpPreference -MAPSReporting 0\n\n- name: Disable windows defender sending sample #2 : never send\n  win_shell: Set-MpPreference -SubmitSamplesConsent 2\n\n- name: Disable network drive scanning\n  win_shell: Set-MpPreference -DisableScanningMappedNetworkDrivesForFullScan $true\n  when: windows_defender_status == \"off\"\n\n- name: Disable realtime monitoring\n  win_shell: Set-MpPreference -DisableRealtimeMonitoring $true\n  when: windows_defender_status == \"off\"\n\n#- name: Uninstall windows defender\n#  win_shell: Uninstall-WindowsFeature -Name Windows-Defender\n"
  },
  {
    "path": "ansible/roles/sync_domains/tasks/main.yml",
    "content": "# https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc835086(v=ws.11)\n- name: \"synchronizes all domains before change schema\"\n  win_shell: repadmin /syncall /AdePq\n  vars:\n    ansible_become: true\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\""
  },
  {
    "path": "ansible/roles/trusts/tasks/main.yml",
    "content": "- name: \"Prepare to trust flush and renew dns\"\n  win_shell: |\n    ipconfig /flushdns\n    ipconfig /renew\n\n# source : https://social.technet.microsoft.com/wiki/contents/articles/11911.active-directory-powershell-how-to-create-forest-trust.aspx\n- name: Add trusts between domain\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $RemoteForest,\n\n          [String]\n          $RemoteAdmin,\n\n          [String]\n          $RemoteAdminPassword\n      )\n      $localforest=[System.DirectoryServices.ActiveDirectory.Forest]::getCurrentForest()\n      try {\n        $localForest.GetTrustRelationship($RemoteForest)\n        $Ansible.Changed = $false\n      } catch [System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundException] {\n        $Ansible.Changed = $true\n        $remoteContext = New-Object -TypeName \"System.DirectoryServices.ActiveDirectory.DirectoryContext\" -ArgumentList @( \"Forest\", $RemoteForest, $RemoteAdmin, $RemoteAdminPassword)\n        $distantForest = [System.DirectoryServices.ActiveDirectory.Forest]::getForest($remoteContext)\n        $localForest.CreateTrustRelationship($distantForest,\"Bidirectional\")\n      }\n    error_action: stop\n    parameters:\n      RemoteForest: \"{{remote_forest}}\"\n      RemoteAdmin: \"{{remote_admin}}\"\n      RemoteAdminPassword: \"{{remote_admin_password}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  register:\n    trust_result\n\n- name: \"Reboot and wait for the AD system to restart\"\n  win_reboot:\n    test_command: \"Get-ADUser -Identity Administrator -Properties *\"\n  when: trust_result.changed\n\n\n#      $localforest=[System.DirectoryServices.ActiveDirectory.Forest]::getCurrentForest()\n#      try {\n#        $trustPassword = \"TrustP@$$w0rd12\"\n#        $localForest.CreateLocalSideOfTrustRelationship($RemoteForest,\"Bidirectional\",$trustPassword)\n#        $Ansible.Changed = $true\n#      } catch [System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectExistsException] {\n#        $Ansible.Changed = $false\n\n- name: Show trust result\n  win_shell: |\n    $obj = Get-CimInstance -Class Microsoft_DomainTrustStatus -Namespace root\\microsoftactivedirectory\n    Write-Output -InputObject $obj\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    domain_name: \"{{domain}}\"\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\""
  },
  {
    "path": "ansible/roles/vulns/acls/tasks/main.yml",
    "content": "# acl : $for, $to, $right, $inheritance\n## acl values :\n# AccessSystemSecurity\n# CreateChild\n# Delete\n# DeleteChild\n# DeleteTree\n# ExtendedRight\n# GenericAll\n# GenericExecute\n# GenericRead\n# GenericWrite\n# ListChildren\n# ListObject\n# ReadControl\n# ReadProperty\n# Self\n# Synchronize\n# WriteDacl\n# WriteOwner\n# WriteProperty \n\n## extend rights\n# \"00299570-246d-11d0-a768-00aa006e0529\" {$right = \"User-Force-Change-Password\"}\n# \"45ec5156-db7e-47bb-b53f-dbeb2d03c40\"  {$right = \"Reanimate-Tombstones\"}\n# \"bf9679c0-0de6-11d0-a285-00aa003049e2\" {$right = \"Self-Membership\"}\n# \"ba33815a-4f93-4c76-87f3-57574bff8109\" {$right = \"Manage-SID-History\"}\n# \"1131f6ad-9c07-11d1-f79f-00c04fc2dcd2\" {$right = \"DS-Replication-Get-Changes-All\"}\n\n# acl extended values allowed : \n# Ext-User-Force-Change-Password', 'Ext-Self-Self-Membership', 'Ext-Write-Self-Membership'\n# ACL abuse scenarios\n# https://sensepost.com/blog/2020/ace-to-rce/\n# https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/abusing-active-directory-acls-aces\n# https://adsecurity.org/?p=3658\n# https://docs.microsoft.com/en-us/previous-versions/tn-archive/ff405676(v=msdn.10)\n\n- name: set acl \n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $for,\n\n          [String]\n          $to,\n\n          [String]\n          $right,\n\n          [String]\n          $inheritance\n      )\n      Import-Module ActiveDirectory\n      Set-Location AD:\n      $aclValues = 'AccessSystemSecurity', 'CreateChild', 'Delete', 'DeleteChild', 'DeleteTree', 'ExtendedRight', 'GenericAll', 'GenericExecute', 'GenericRead', 'GenericWrite', 'ListChildren', 'ListObject', 'ReadControl', 'ReadProperty', 'Self', 'Synchronize', 'WriteDacl', 'WriteOwner', 'WriteProperty'\n      $aclExtendValues = 'Ext-User-Force-Change-Password', 'Ext-Self-Self-Membership', 'Ext-Write-Self-Membership'\n      if ($for.StartsWith(\"NT AUTHORITY\")) {\n        $forSID = New-Object System.Security.Principal.NTAccount \"$for\"\n      } else {\n        $forSID = New-Object System.Security.Principal.SecurityIdentifier (Get-ADObject -Filter \"SamAccountName -eq '$for'\" -Properties objectSID).objectSID\n      }\n\n      try {\n        $objAcl = get-acl -Path \"$to\" -ErrorAction Stop\n        $objOU = $to\n        $objFound=$true\n      } catch [System.Management.Automation.ItemNotFoundException]{\n        $objFound=$false\n      }\n\n      if (-not $objFound) {\n        $extra_args = @{}\n        if ($to -match \"\\\\\") {\n          $extra_args.Server = $to.Split(\"\\\")[0]\n          $to = $to.Split(\"\\\")[1]\n        }\n        $toObj = Get-ADObject -Filter \"SamAccountName -eq '$to'\" @extra_args\n        $objOU = ($toObj).DistinguishedName\n        $objAcl = get-acl -Path \"$objOU\"\n      }\n\n      $type =  [System.Security.AccessControl.AccessControlType] \"Allow\"\n      $inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance] $inheritance\n\n      $aclExtendedValueRightGUID = @{\n        \"Ext-User-Force-Change-Password\" = @(\"ExtendedRight\",\"00299570-246d-11d0-a768-00aa006e0529\")\n        \"Ext-Write-Self-Membership\" = @(\"WriteProperty\",\"bf9679c0-0de6-11d0-a285-00aa003049e2\")\n        \"Ext-Self-Self-Membership\" = @(\"Self\",\"bf9679c0-0de6-11d0-a285-00aa003049e2\")\n      }\n\n      $Ansible.Changed = $false\n      if ($aclValues.contains($right)) {\n        $adRight =  [System.DirectoryServices.ActiveDirectoryRights] $right\n        $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $forSID,$adRight,$type,$inheritanceType\n      }\n      if ($aclExtendValues.contains($right)) {\n        $extendedRightGUID = $aclExtendedValueRightGUID[$right][1]\n        $extright = $aclExtendedValueRightGUID[$right][0]\n        $adRight =  [System.DirectoryServices.ActiveDirectoryRights] $extright\n        $ace = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $forSID,$extright,$type,$extendedRightGUID,$inheritanceType\n      }\n      if ($ace) {\n        $objAcl.AddAccessRule($ace)\n        Set-Acl -AclObject $objAcl -path \"$objOU\"\n        $Ansible.Changed = $true\n      }\n    parameters:\n      for: \"{{item.value.for}}\"\n      to: \"{{item.value.to}}\"\n      right: \"{{item.value.right}}\"\n      inheritance: \"{{item.value.inheritance}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  with_dict: \"{{ vulns_vars }}\""
  },
  {
    "path": "ansible/roles/vulns/adcs_esc10_case1/tasks/main.yml",
    "content": "- name: Set StrongCertificateBindingEnforcement to 0\n  win_regedit:\n    path: HKLM:\\SYSTEM\\CurrentControlSet\\Services\\Kdc\n    name: StrongCertificateBindingEnforcement\n    data: 0x0\n    type: dword\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    domain_name: \"{{domain}}\"\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\""
  },
  {
    "path": "ansible/roles/vulns/adcs_esc10_case2/tasks/main.yml",
    "content": "- name: Set CertificateMappingMethods to 0x4 (UPN)\n  win_regedit:\n    path: HKLM:\\System\\CurrentControlSet\\Control\\SecurityProviders\\Schannel\n    name: CertificateMappingMethods\n    data: 0x4\n    type: dword\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    domain_name: \"{{domain}}\"\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\""
  },
  {
    "path": "ansible/roles/vulns/adcs_esc11/handlers/main.yml",
    "content": "- name: restart-adcs\n  win_shell: Restart-Service certsvc"
  },
  {
    "path": "ansible/roles/vulns/adcs_esc11/tasks/main.yml",
    "content": "- name: Disable IF_ENFORCEENCRYPTICERTREQUEST flag (ESC11)\n  win_shell: |\n     certutil -setreg CA\\InterfaceFlags -IF_ENFORCEENCRYPTICERTREQUEST\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  notify: restart-adcs"
  },
  {
    "path": "ansible/roles/vulns/adcs_esc13/files/esc13.ps1",
    "content": "# Code from LUDUS ESC13 role\n# Licence GPL-3.0\n# https://github.com/badsectorlabs/ludus_adcs/blob/main/files/esc13.ps1\n\nparam(\n    [Parameter(Mandatory=$true)]\n    [string]$esc13group,\n    \n    [Parameter(Mandatory=$true)]\n    [string]$esc13templateName\n)\n\n\n# Import modules (just in case)\nimport-module ADCSTemplate\nimport-module ActiveDirectory\n\n # Function to generate a random hexadecimal string of a given length\n Function Get-RandomHex {\n    param ([int]$Length)\n    $Hex = '0123456789ABCDEF'\n    $Return = ''\n    1..$Length | ForEach-Object {\n        $Return += $Hex.Substring((Get-Random -Minimum 0 -Maximum 16),1)\n    }\n    Return $Return\n}\n\n# Function to check if a given OID is unique\nFunction IsUniqueOID {\n    param ($cn, $TemplateOID, $ConfigNC)\n    $Search = Get-ADObject -Filter {cn -eq $cn -and msPKI-Cert-Template-OID -eq $TemplateOID} -SearchBase \"CN=OID,CN=Public Key Services,CN=Services,$ConfigNC\"\n    If ($Search) {$False} Else {$True}\n}\n\n# Function to generate a new unique OID\nFunction New-TemplateOID {\n    Param($ConfigNC)\n    do {\n        $OID_Part_1 = Get-Random -Minimum 10000000 -Maximum 99999999\n        $OID_Part_2 = Get-Random -Minimum 10000000 -Maximum 99999999\n        $OID_Part_3 = Get-RandomHex -Length 32\n        $OID_Forest = Get-ADObject -Identity \"CN=OID,CN=Public Key Services,CN=Services,$ConfigNC\" -Properties msPKI-Cert-Template-OID |\n            Select-Object -ExpandProperty msPKI-Cert-Template-OID\n        $msPKICertTemplateOID = \"$OID_Forest.$OID_Part_1.$OID_Part_2\"\n        $Name = \"$OID_Part_2.$OID_Part_3\"\n    } until (IsUniqueOID -cn $Name -TemplateOID $msPKICertTemplateOID -ConfigNC $ConfigNC)\n    Return @{\n        TemplateOID  = $msPKICertTemplateOID\n        TemplateName = $Name\n    }\n}\n\n# Get the configuration naming context\n$ADRootDSE = Get-ADRootDSE\n$ConfigNC = $ADRootDSE.configurationNamingContext\n\n# Define the display name and the template\n$IssuanceName = \"IssuancePolicyESC13\"\n$ESC13Template = \"CN=$esc13templateName,CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC\"\n\n# Generate a new unique OID\n$OID = New-TemplateOID -ConfigNC $ConfigNC\n\n# Define the path to the OID\n$TemplateOIDPath = \"CN=OID,CN=Public Key Services,CN=Services,$ConfigNC\"\n\n# Create a new AD object with the generated OID\n$oa = @{\n    'DisplayName' = $IssuanceName\n    'Name' = $IssuanceName\n    'flags' = [System.Int32]'2'\n    'msPKI-Cert-Template-OID' = $OID.TemplateOID\n }\n$theresults = New-ADObject -Path $TemplateOIDPath -OtherAttributes $oa -Name $OID.TemplateName -Type 'msPKI-Enterprise-Oid'\n\n# Get the new OID object\n$OIDContainer = \"CN=OID,CN=Public Key Services,CN=Services,\"+$ConfigNC\n$OIDs = Get-ADObject -Filter * -SearchBase $OIDContainer -Properties DisplayName,Name,msPKI-Cert-Template-OID,msDS-OIDToGroupLink\n$newOIDObj = ($OIDS | where {$_.DisplayName -eq $IssuanceName })\n$newOIDValue = $newOIDObj | select -ExpandProperty msPKI-Cert-Template-OID\n\n# Get the ESC13 template object for updating\n$adObject = Get-ADObject $ESC13Template -Properties msPKI-Certificate-Policy\n\n# Get the current policies\n$policies = $adObject.'msPKI-Certificate-Policy'\n\n# Add new OID to the policies\n$newPolicy = $newOIDValue # replace with your new OID\n$policies = $newPolicy\n\n# Convert policies to an array of strings\n$policies = $policies | ForEach-Object { $_.ToString() }\n\n# Update the ESC13 template AD object\nSet-ADObject -Identity $adObject.DistinguishedName -Replace @{ 'msPKI-Certificate-Policy' = $policies } \n\n# Get DN of the ESC13 Group\n$ludus_esc13_group_dn = (Get-ADGroup $esc13group).DistinguishedName\n$ludus_esc13_group_dn  \n\n# Get Distinguished Name of the ESC13 OID Issuance Policy we created\n# Thanks to Jonas (https://twitter.com/Jonas_B_K) for helping with this!\n$ADRootDSE = Get-ADRootDSE\n$ConfigurationNC = $ADRootDSE.configurationNamingContext\n$OIDContainer = \"CN=OID,CN=Public Key Services,CN=Services,\"+$ConfigurationNC\n$OIDs = Get-ADObject -Filter * -SearchBase $OIDContainer -Properties DisplayName,Name,msPKI-Cert-Template-OID,msDS-OIDToGroupLink\n$esc13OID_dn = ($OIDS | where {$_.DisplayName -eq $IssuanceName }).DistinguishedName[0]\n$esc13OID_dn\n\n# Create a DirectoryEntry object for the Issuance Policy OID\n$object = New-Object System.DirectoryServices.DirectoryEntry(\"LDAP://$esc13OID_dn\")\n\n# Set the msDS-OIDToGroupLink property to the DN of the ESC13 group\n$Toset = $ludus_esc13_group_dn\n$object.Properties[\"msDS-OIDToGroupLink\"].Value = $Toset\n$object.CommitChanges()\n$object.RefreshCache()\n$object | select msDS-OIDToGroupLink"
  },
  {
    "path": "ansible/roles/vulns/adcs_esc13/tasks/main.yml",
    "content": "# adapted from ludus ESC13\n# RUN me on DC\n# https://github.com/badsectorlabs/ludus_adcs/blob/main/tasks/esc13.yml\n\n- name: Copy ESC13 script to remote host\n  ansible.windows.win_copy:\n    src: files/esc13.ps1\n    dest: C:\\setup\\esc13.ps1\n\n- name: Run ESC13 script\n  ansible.windows.win_shell: |\n    C:\\setup\\esc13.ps1 -esc13group '{{ item.value.adcs_esc13_group }}' -esc13templateName '{{ item.value.adcs_esc13_template }}'\n  become: true\n  become_method: runas\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    domain_name: \"{{domain}}\"\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  with_dict: \"{{ vulns_vars }}\""
  },
  {
    "path": "ansible/roles/vulns/adcs_esc15/tasks/main.yml",
    "content": "- name: Run ESC15\n  ansible.windows.win_powershell:\n    script: |\n      # code from ludus module (also GPL)\n      # https://github.com/badsectorlabs/ludus_adcs/blob/main/files/esc15.ps1\n      # Import ADCSTemplate module\n      Import-Module ADCSTemplate\n\n      # Define the template and group name\n      $displayName = \"Web Server\"\n      $groupName = \"Domain Users\"\n\n      Set-ADCSTemplateACL -DisplayName $displayName -Type Allow -Identity $groupName -Enroll\n    error_action: stop\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    domain_name: \"{{domain}}\"\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\""
  },
  {
    "path": "ansible/roles/vulns/adcs_esc6/handlers/main.yml",
    "content": "- name: restart-adcs\n  win_shell: Restart-Service certsvc"
  },
  {
    "path": "ansible/roles/vulns/adcs_esc6/tasks/main.yml",
    "content": "\n- name: \"Configure ATTRIBUTESUBJECTALTNAME2 on CA - ESC6\"\n  win_shell: |\n    certutil -setreg policy\\Editflags +EDITF_ATTRIBUTESUBJECTALTNAME2\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  notify: restart-adcs   "
  },
  {
    "path": "ansible/roles/vulns/adcs_esc7/tasks/main.yml",
    "content": "# Code adapted from ludus adcs module : https://github.com/badsectorlabs/ludus_adcs/blob/main/files/esc7.ps1\n# RUN me on DC\n- name: Install module PSPKI\n  win_shell: |\n    Install-Module PSPKI -Force\n\n- name: ADD ManageCA rights\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n      param (\n          [String]\n          $caManagerUser\n      )\n      if (Get-Module -ListAvailable -Name PSPKI) {\n        $Ansible.Changed = $false\n      } else {\n        Import-Module -Name PSPKI\n        $caHostname = Get-CertificationAuthority | Select-Object -ExpandProperty ComputerName\n        try {\n          Get-CertificationAuthority \"$caHostname\" | Get-CertificationAuthorityAcl | Add-CertificationAuthorityAcl -Identity \"$caManagerUser\" -AccessType \"Allow\" -AccessMask \"ManageCa\" | Set-CertificationAuthorityAcl -RestartCA\n          $Ansible.Changed = $true\n        } catch {\n          $Ansible.Changed = $false\n        }\n      }\n    error_action: stop\n    parameters:\n      caManagerUser: \"{{item.value.ca_manager}}\"\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    domain_name: \"{{domain}}\"\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  with_dict: \"{{ vulns_vars }}\"\n"
  },
  {
    "path": "ansible/roles/vulns/adcs_templates/files/ADCSTemplate/.gitignore",
    "content": ".DS_Store\n"
  },
  {
    "path": "ansible/roles/vulns/adcs_templates/files/ADCSTemplate/ADCSTemplate.psm1",
    "content": "#requires -Version 5.0 -Modules ActiveDirectory\r\n\r\nFunction Get-RandomHex {\r\nparam ([int]$Length)\r\n    $Hex = '0123456789ABCDEF'\r\n    [string]$Return = $null\r\n    For ($i=1;$i -le $length;$i++) {\r\n        $Return += $Hex.Substring((Get-Random -Minimum 0 -Maximum 16),1)\r\n    }\r\n    Return $Return\r\n}\r\n\r\nFunction IsUniqueOID {\r\nparam ($cn,$TemplateOID,$Server,$ConfigNC)\r\n    $Search = Get-ADObject -Server $Server `\r\n        -SearchBase \"CN=OID,CN=Public Key Services,CN=Services,$ConfigNC\" `\r\n        -Filter {cn -eq $cn -and msPKI-Cert-Template-OID -eq $TemplateOID}\r\n    If ($Search) {$False} Else {$True}\r\n}\r\n\r\nFunction New-TemplateOID {\r\nParam($Server,$ConfigNC)\r\n    <#\r\n    OID CN/Name                                                         [10000000-99999999].[32 hex characters (MD5hash)]\r\n    OID msPKI-Cert-Template-OID    [Forest base OID].[1000000-99999999].[10000000-99999999]  <--- second number same as first number in OID name\r\n    #>\r\n    do {\r\n        $OID_Part_1 = Get-Random -Minimum 10000000 -Maximum 99999999\r\n        $OID_Part_2 = Get-Random -Minimum 10000000 -Maximum 99999999\r\n        $OID_Part_3 = Get-RandomHex -Length 32\r\n        $OID_Forest = Get-ADObject -Server $Server `\r\n            -Identity \"CN=OID,CN=Public Key Services,CN=Services,$ConfigNC\" `\r\n            -Properties msPKI-Cert-Template-OID |\r\n            Select-Object -ExpandProperty msPKI-Cert-Template-OID\r\n        $msPKICertTemplateOID = \"$OID_Forest.$OID_Part_1.$OID_Part_2\"\r\n        $Name = \"$OID_Part_2.$OID_Part_3\"\r\n    } until (IsUniqueOID -cn $Name -TemplateOID $msPKICertTemplateOID -Server $Server -ConfigNC $ConfigNC)\r\n    Return @{\r\n        TemplateOID  = $msPKICertTemplateOID\r\n        TemplateName = $Name\r\n    }\r\n}\r\n\r\n\r\n<#\r\n.SYNOPSIS\r\nReturns the properties of either a single or all Active Directory Certificate Template(s).\r\n.DESCRIPTION\r\nReturns the properties of either a single or list of Active Directory Certificate Template(s)\r\ndepending on whether a DisplayName parameter was passed.\r\n.PARAMETER DisplayName\r\nName of an AD CS template to retrieve.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.EXAMPLE\r\nPS C:\\> Get-ADCSTemplate\r\n.EXAMPLE\r\nPS C:\\> Get-ADCSTemplate -DisplayName PowerShellCMS\r\n.EXAMPLE\r\nPS C:\\> Get-ADCSTemplate | Sort-Object Name | ft Name, Created, Modified\r\n.EXAMPLE\r\nPS C:\\> ###View template permissions\r\n(Get-ADCSTemplate pscms).nTSecurityDescriptor\r\n(Get-ADCSTemplate pscms).nTSecurityDescriptor.Sddl\r\n(Get-ADCSTemplate pscms).nTSecurityDescriptor.Access\r\nConvertFrom-SddlString -Sddl (Get-ADCSTemplate pscms).nTSecurityDescriptor.sddl -Type ActiveDirectoryRights\r\n.NOTES\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n#>\r\nFunction Get-ADCSTemplate {\r\nparam(\r\n    [parameter(Position=0)]\r\n    [string]\r\n    $DisplayName,\r\n\r\n    [string]\r\n    $Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\r\n)\r\n    If ($PSBoundParameters.ContainsKey('DisplayName')) {\r\n        $LDAPFilter = \"(&(objectClass=pKICertificateTemplate)(displayName=$DisplayName))\"\r\n    } Else {\r\n        $LDAPFilter = '(objectClass=pKICertificateTemplate)'\r\n    }\r\n\r\n    $ConfigNC     = $((Get-ADRootDSE -Server $Server).configurationNamingContext)\r\n    $TemplatePath = \"CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n    Get-ADObject -SearchScope Subtree -SearchBase $TemplatePath -LDAPFilter $LDAPFilter -Properties * -Server $Server\r\n}\r\n\r\n\r\n<#\r\n.SYNOPSIS\r\nAdds an ACL to an Active Directory Certificate template.\r\n.DESCRIPTION\r\nAdds an ACL to an Active Directory Certificate template.\r\nDefault permission is read (without the Enroll or AutoEnroll switches).\r\n.PARAMETER DisplayName\r\nName of an AD CS template to receive the ACL.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.PARAMETER Type\r\nACL type: Allow or Deny\r\n.PARAMETER Identity\r\nString or string array of Active Directory identities (users or groups)\r\n.PARAMETER Enroll\r\nSet the Enroll permission\r\n.PARAMETER AutoEnroll\r\nSet the AutoEnroll permission\r\n.EXAMPLE\r\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Allow -Identity 'CONTOSO\\Servers Group' -Enroll\r\n.EXAMPLE\r\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Allow -Identity 'CONTOSO\\Servers Group','CONTOSO\\Workstations Group' -Enroll -AutoEnroll\r\n.EXAMPLE\r\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Deny -Identity 'CONTOSO\\Servers Group'\r\n.NOTES\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n#>\r\nFunction Set-ADCSTemplateACL {\r\nparam(\r\n    [parameter(Mandatory)]\r\n    [string]$DisplayName,\r\n    [string]$Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0],\r\n    [ValidateSet('Allow','Deny')]\r\n    [string]$Type = 'Allow',\r\n    [string[]]$Identity,\r\n    [switch]$Enroll,\r\n    [switch]$AutoEnroll\r\n)\r\n    ## Potential issue here that the AD: drive may not be targetting the selected DC in the -SERVER parameter\r\n    $TemplatePath        = \"AD:\\\" + (Get-ADCSTemplate -DisplayName $DisplayName -Server $Server).DistinguishedName\r\n    $acl                 = Get-ACL $TemplatePath\r\n    $InheritedObjectType = [GUID]'00000000-0000-0000-0000-000000000000'\r\n    ForEach ($Group in $Identity) {\r\n        $account = New-Object System.Security.Principal.NTAccount($Group)\r\n        $sid     = $account.Translate([System.Security.Principal.SecurityIdentifier])\r\n\r\n        If ($Type -ne 'Deny') {\r\n            # Read, but only if Allow\r\n            $ObjectType = [GUID]'00000000-0000-0000-0000-000000000000'\r\n            $ace        = New-Object System.DirectoryServices.ActiveDirectoryAccessRule `\r\n                $sid, 'GenericRead', $Type, $ObjectType, 'None', $InheritedObjectType\r\n            $acl.AddAccessRule($ace)\r\n        }\r\n\r\n        If ($Enroll) {\r\n            $ObjectType = [GUID]'0e10c968-78fb-11d2-90d4-00c04f79dc55'\r\n            $ace        = New-Object System.DirectoryServices.ActiveDirectoryAccessRule `\r\n                $sid, 'ExtendedRight', $Type, $ObjectType, 'None', $InheritedObjectType\r\n            $acl.AddAccessRule($ace)\r\n        }\r\n\r\n        If ($AutoEnroll) {\r\n            $ObjectType = [GUID]'a05b8cc2-17bc-4802-a710-e7c15ab866a2'\r\n            $ace        = New-Object System.DirectoryServices.ActiveDirectoryAccessRule `\r\n                $sid, 'ExtendedRight', $Type, $ObjectType, 'None', $InheritedObjectType\r\n            $acl.AddAccessRule($ace)\r\n        }\r\n    }\r\n    Set-ACL $TemplatePath -AclObject $acl\r\n}\r\n\r\n\r\n<#\r\n.SYNOPSIS\r\nReturns a JSON string with the properties of an Active Directory certificate template.\r\n.DESCRIPTION\r\nReturns a JSON string with the properties of an Active Directory certificate template.\r\nBy default returns only the PKI-related properties of the object. These properties are\r\nsufficient for passing to the New-ADCSTemplate function.\r\n.PARAMETER DisplayName\r\nDisplayName for the certificate to export.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.PARAMETER Detailed\r\nIncludes all ADObject properties of the template. These are not required for \r\nuse with the New-ADCSTemplate function.\r\n.NOTES\r\nC.R.U.D. AD CS Template Operations in this module.\r\nNo longer have to use the cert GUI to clone a template and build a new one.\r\nCreate one manually the first time in the GUI, then export it to JSON.\r\nPass the JSON in your new environment (file, here string, DSC, etc.) to build from scratch.\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n.EXAMPLE\r\nPS C:\\> Export-ADCSTemplate -DisplayName PowerShellCMS\r\n.EXAMPLE\r\nPS C:\\> Export-ADCSTemplate -DisplayName PowerShellCMS -Detailed\r\n.EXAMPLE\r\n### Backup all the templates to JSON\r\nmd C:\\ADCSTemplates -ErrorAction SilentlyContinue\r\ncd C:\\ADCSTemplates\r\n(Get-ADCSTemplate).name | ForEach-Object {\"Exporting $_\"; Export-ADCSTemplate -DisplayName $_ | Out-File .\\$_.json -Force}\r\ndir\r\n.EXAMPLE\r\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS-NEW -JSON (Export-ADCSTemplate -DisplayName PowerShellCMS-OLD)\r\n#>\r\nFunction Export-ADCSTemplate {\r\nparam(\r\n    [parameter(Mandatory)]\r\n    [string]$DisplayName,\r\n    [string]$Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0],\r\n    [switch]$Detailed   # Detailed output is not required for export/import. Use for documentation/backup purposes.\r\n)\r\n    If ($Detailed) {\r\n        Get-ADCSTemplate -DisplayName $DisplayName -Server $Server |\r\n            ConvertTo-Json\r\n    } Else {\r\n        Get-ADCSTemplate -DisplayName $DisplayName -Server $Server |\r\n            Select-Object -Property name, displayName, objectClass, flags, revision, *pki* |\r\n            ConvertTo-Json\r\n    }\r\n}\r\n\r\n<#\r\n.SYNOPSIS\r\nCreates a new Active Directory Certificate Services template based on a JSON export.\r\n.DESCRIPTION\r\nCreates a new Active Directory Certificate Services template based on a JSON export.\r\nOptionally can permission and publish the template (best practice).\r\n.PARAMETER DisplayName\r\nDisplayName for the certificate template to create. This does not have to match\r\nthe original name of the exported template.\r\n.PARAMETER JSON\r\nJSON string output from Export-ADCSTemplate. Defines the template to create.\r\nCan be retrieved from file using Get-Content -Raw.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.PARAMETER Identity\r\nString or string array of Active Directory identities (users or groups).\r\nThis is optional for permissioning the template.\r\n.PARAMETER AutoEnroll\r\nDefault permission is Read and Enroll. Use this switch to also grant AutoEnroll \r\nto the identity. Only used when Identity parameter is used.\r\n.PARAMETER Publish\r\nPublish the template to *ALL* Certificate Authority issuers. Use with caution\r\nin production environments. You may want to manually publish to only specific\r\nCertificate Authorities in production. In a lab this is ideal.\r\n.NOTES\r\nThis function does not use the official (complicated) API for PKI management.\r\nInstead it creates the exact same AD objects that are generated by the API,\r\nincluding AD forest-specific OIDs.\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n.EXAMPLE\r\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS -JSON (Get-Content .\\pscms.json -Raw)\r\n.EXAMPLE\r\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS -JSON (Get-Content .\\pscms.json -Raw) -Server dc1.contoso.com -Identity G_DSCNodes -AutoEnroll -Publish\r\n\r\n# From a client configured for AD CS autoenrollment:\r\n$Req = @{\r\n    Template          = 'PowerShellCMS'\r\n    Url               = 'ldap:'\r\n    CertStoreLocation = 'Cert:\\LocalMachine\\My'\r\n}\r\nGet-Certificate @Req\r\n# Note: If you have the Carbon module installed, it conflicts with Get-Certificate native cmdlet.\r\n\r\n$DocEncrCert = (dir Cert:\\LocalMachine\\My -DocumentEncryptionCert | Sort-Object NotBefore)[-1]\r\nProtect-CmsMessage -To $DocEncrCert -Content \"Encrypted with my new cert from the new template!\"\r\n.EXAMPLE\r\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS-NEW -JSON (Export-ADCSTemplate -DisplayName PowerShellCMS-OLD)\r\n#>\r\nFunction New-ADCSTemplate {\r\nparam(\r\n    [parameter(Mandatory)]\r\n    [string]$DisplayName,   # name in JSON export is ignored\r\n    [parameter(Mandatory)]\r\n    [string]$JSON,\r\n    [string]$Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0],\r\n    [string[]]$Identity, # = \"$((Get-ADDomain).NetBIOSName)\\Domain Computers\",\r\n    [switch]$AutoEnroll,\r\n    [switch]$Publish\r\n)\r\n    ### Put GroupName and AutoEnroll into a parameter set\r\n\r\n    # Manually import AD module to get AD: drive used later for permissions\r\n    Import-Module ActiveDirectory -Verbose:$false\r\n\r\n    $ConfigNC = $((Get-ADRootDSE -Server $Server).configurationNamingContext)\r\n\r\n    #region CREATE OID\r\n    <#\r\n    CN                              : 14891906.F2AC4390685318BD1D950A66EDB50FF4\r\n    DisplayName                     : TemplateNameHere\r\n    DistinguishedName               : CN=14891906.F2AC4390685318BD1D950A66EDB50FF4,CN=OID,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=com\r\n    dSCorePropagationData           : {1/1/1601 12:00:00 AM}\r\n    flags                           : 1\r\n    instanceType                    : 4\r\n    msPKI-Cert-Template-OID         : 1.3.6.1.4.1.311.21.8.11489019.14294623.5588661.594850.12204198.151.6616009.14891906\r\n    Name                            : 14891906.F2AC4390685318BD1D950A66EDB50FF4\r\n    ObjectCategory                  : CN=ms-PKI-Enterprise-Oid,CN=Schema,CN=Configuration,DC=contoso,DC=com\r\n    ObjectClass                     : msPKI-Enterprise-Oid\r\n    #>\r\n    $OID = New-TemplateOID -Server $Server -ConfigNC $ConfigNC\r\n    $TemplateOIDPath = \"CN=OID,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n    $oa = @{\r\n\t    'DisplayName' = $DisplayName\r\n\t    'flags' = [System.Int32]'1'\r\n\t    'msPKI-Cert-Template-OID' = $OID.TemplateOID\r\n    }\r\n    New-ADObject -Path $TemplateOIDPath -OtherAttributes $oa -Name $OID.TemplateName -Type 'msPKI-Enterprise-Oid' -Server $Server\r\n    #endregion\r\n\r\n    #region CREATE TEMPLATE\r\n    # https://docs.microsoft.com/en-us/powershell/dsc/securemof#certificate-requirements\r\n    # https://blogs.technet.microsoft.com/option_explicit/2012/04/09/pki-certificates-and-the-x-509-standard/\r\n    # https://technet.microsoft.com/en-us/library/cc776447(v=ws.10).aspx\r\n    $import = $JSON | ConvertFrom-Json\r\n    $oa = @{ 'msPKI-Cert-Template-OID' = $OID.TemplateOID }\r\n    ForEach ($prop in ($import | Get-Member -MemberType NoteProperty)) {\r\n        Switch ($prop.Name) {\r\n            { $_ -in 'flags',\r\n                    'msPKI-Certificate-Name-Flag',\r\n                    'msPKI-Enrollment-Flag',\r\n                    'msPKI-Minimal-Key-Size',\r\n                    'msPKI-Private-Key-Flag',\r\n                    'msPKI-Template-Minor-Revision',\r\n                    'msPKI-Template-Schema-Version',\r\n                    'msPKI-RA-Signature',\r\n                    'pKIMaxIssuingDepth',\r\n                    'pKIDefaultKeySpec',\r\n                    'revision'\r\n            } { $oa.Add($_,[System.Int32]$import.$_); break }\r\n\r\n            { $_ -in 'msPKI-Certificate-Application-Policy',\r\n                    'pKICriticalExtensions',\r\n                    'pKIDefaultCSPs',\r\n                    'pKIExtendedKeyUsage',\r\n                    'msPKI-RA-Application-Policies'\r\n            } { $oa.Add($_,[Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]$import.$_); break }\r\n\r\n            { $_ -in 'pKIExpirationPeriod',\r\n                    'pKIKeyUsage',\r\n                    'pKIOverlapPeriod'\r\n            } { $oa.Add($_,[System.Byte[]]$import.$_); break }\r\n\r\n        }\r\n    }\r\n    $TemplatePath = \"CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n    New-ADObject -Path $TemplatePath -OtherAttributes $oa -Name $DisplayName.Replace(' ','') `\r\n        -DisplayName $DisplayName -Type pKICertificateTemplate -Server $Server\r\n    #endregion\r\n\r\n    #region PERMISSIONS\r\n    ## Potential issue here that the AD: drive may not be targetting the selected DC in the -SERVER parameter\r\n    If ($PSBoundParameters.ContainsKey('Identity')) {\r\n        If ($AutoEnroll) {\r\n            Set-ADCSTemplateACL -DisplayName $DisplayName -Server $Server -Type Allow -Identity $Identity -Enroll -AutoEnroll\r\n        } Else {\r\n            Set-ADCSTemplateACL -DisplayName $DisplayName -Server $Server -Type Allow -Identity $Identity -Enroll\r\n        }\r\n    }\r\n    #endregion\r\n\r\n    #region ISSUE\r\n    If ($Publish) {\r\n        ### WARNING: Issues on all available CAs. Test in your environment.\r\n        $EnrollmentPath = \"CN=Enrollment Services,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n        $CAs = Get-ADObject -SearchBase $EnrollmentPath -SearchScope OneLevel -Filter * -Server $Server\r\n        ForEach ($CA in $CAs) {\r\n            Set-ADObject -Identity $CA.DistinguishedName -Add @{certificateTemplates=$DisplayName.Replace(' ','')} -Server $Server\r\n        }\r\n    }\r\n    #endregion\r\n}\r\n\r\n\r\n<#\r\n.SYNOPSIS\r\nRemoves a certificate template from Active Directory.\r\n.DESCRIPTION\r\nRemoves the template from any issuers where it is published.\r\nRemoves the template itself.\r\nRemoves the unique OID object of the template.\r\n.PARAMETER DisplayName\r\nDisplayName for the certificate template to delete.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.EXAMPLE\r\nPS C:\\> Remove-ADCSTemplate -DisplayName PowerShellCMS\r\n.EXAMPLE\r\nPS C:\\> (Get-ADCSTemplate).name | Where-Object {$_ -like \"PowerShellCMS*\"} | ForEach-Object {Remove-ADCSTemplate -DisplayName $_ -Verbose}\r\n.NOTES\r\nUse with caution!\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n#>\r\nFunction Remove-ADCSTemplate {\r\n[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='High')]\r\nparam(\r\n    [parameter(Mandatory)]\r\n    [string]$DisplayName,\r\n    [string]$Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\r\n)\r\n    if ($pscmdlet.ShouldProcess($DisplayName, 'Remove certificate template')) {\r\n        $ConfigNC = $((Get-ADRootDSE -Server $Server).configurationNamingContext)\r\n\r\n        $Template = Get-ADCSTemplate -DisplayName $DisplayName -Server $Server\r\n\r\n        #region REMOVE ISSUE IF IT EXISTS\r\n        $EnrollmentPath = \"CN=Enrollment Services,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n        $CAs = Get-ADObject -SearchBase $EnrollmentPath -SearchScope OneLevel -Filter * -Server $Server\r\n        ForEach ($CA in $CAs) {\r\n            Set-ADObject -Identity $CA.DistinguishedName -Remove @{certificateTemplates=$Template.cn} -Server $Server -Confirm:$false\r\n        }\r\n        #endregion\r\n\r\n        #region REMOVE TEMPLATE\r\n        Remove-ADObject -Identity $Template.distinguishedName -Server $Server -Confirm:$false\r\n        #endregion\r\n\r\n        #region REMOVE OID\r\n        $TemplateOIDPath = \"CN=OID,CN=Public Key Services,CN=Services,$ConfigNC\"\r\n        Get-ADObject -SearchBase $TemplateOIDPath -LDAPFilter \"(DisplayName=$DisplayName)\" -Server $Server | Remove-ADObject -Confirm:$false\r\n        #endregion\r\n    }\r\n}\r\n\r\n\r\n<#\r\n.SYNOPSIS\r\nMaps a PowerShell drive to the Active Directory Certificate Services location.\r\n.DESCRIPTION\r\nMaps a PowerShell drive to the Active Directory Certificate Services location \r\nof the Configuration partition under CN=Public Key Services,CN=Services,... .\r\nThe new drive is ADCS:. This is purely for convenience of checking the objects\r\nupdated by functions in the ADCSTemplate module.\r\n.PARAMETER Server\r\nFQDN of Active Directory Domain Controller to target for the operation.\r\nWhen not specified it will search for the nearest Domain Controller.\r\n.EXAMPLE\r\nPS C:\\> New-ADCSDrive\r\nPS C:\\> Set-Location ADCS:\r\n.EXAMPLE\r\n### Explore templates with drive\r\nNew-ADCSDrive\r\nGet-PSDrive\r\ncd ADCS:\r\ndir\r\n\r\n# List templates\r\ncd '.\\CN=Certificate Templates'\r\ndir\r\ndir | fl *\r\ndir *WebServer*\r\n\r\n# list CAs\r\ncd \\\r\ncd '.\\CN=Enrollment Services'\r\ndir\r\ncd C:\r\n.NOTES\r\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\r\n#>\r\nFunction New-ADCSDrive {\r\nparam(\r\n    [string]$Server = (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\r\n)\r\n    $ConfigNC     = $((Get-ADRootDSE -Server $Server).configurationNamingContext)\r\n    New-PSDrive -Name ADCS -PSProvider ActiveDirectory -Root \"CN=Public Key Services,CN=Services,$ConfigNC\" -Server $Server -Scope Global\r\n}\r\n\r\n\r\nExport-ModuleMember -Function *-ADCS*\r\n"
  },
  {
    "path": "ansible/roles/vulns/adcs_templates/files/ADCSTemplate/Examples/Build-ADCS.ps1",
    "content": "\n\nconfiguration CreateADDomainWithCS\n{ \n   param \n   ( \n        [Parameter(Mandatory)]\n        [String]$DomainName,\n\n        [Parameter(Mandatory)]\n        [System.Management.Automation.PSCredential]$AdminCreds,\n\n        [Int]$RetryCount = 60,\n        [Int]$RetryIntervalSec = 5\n    ) \n    \n    Import-DscResource -ModuleName PSDesiredStateConfiguration\n    Import-DscResource -ModuleName xActiveDirectory -ModuleVersion 2.17.0.0\n    Import-DscResource -ModuleName xAdcsDeployment -ModuleVersion 1.4.0.0\n    Import-DscResource -ModuleName ADCSTemplate -ModuleVersion 1.0.1.0\n    \n    [System.Management.Automation.PSCredential]$DomainCreds = New-Object System.Management.Automation.PSCredential (\"$DomainName\\$($AdminCreds.UserName)\", $AdminCreds.Password)\n\n    Node $AllNodes.NodeName\n    {\n        LocalConfigurationManager\n        {\n            ActionAfterReboot = 'ContinueConfiguration'\n            ConfigurationMode = 'ApplyOnly'\n            RebootNodeIfNeeded = $true\n            AllowModuleOverWrite = $true\n        }\n\n        WindowsFeature ADDSInstall \n        { \n            Ensure = 'Present'\n            Name = 'AD-Domain-Services'\n        }  \n\n        WindowsFeature ADDSPowerShell\n        { \n            Ensure = 'Present' \n            Name = 'RSAT-AD-PowerShell'\n        }\n\n        # Optional GUI tools\n        WindowsFeature ADDSTools\n        { \n            Ensure = 'Present' \n            Name = 'RSAT-ADDS'\n        }\n\n        xADDomain FirstDS \n        {\n            DomainName = $DomainName\n            DomainAdministratorCredential = $DomainCreds\n            SafemodeAdministratorPassword = $DomainCreds\n            DomainNetbiosName = ($DomainName -split '\\.')[0]\n            DependsOn = \"[WindowsFeature]ADDSInstall\"\n        }\n<#\n        #This resource is broken as of 2.17.0.0.\n        #See Script resource alternative below.\n        #Revert to using this resource when it is fixed.\n\n        xWaitForADDomain DscForestWait\n        {\n            DomainName = $DomainName\n            DomainUserCredential = $DomainCreds\n            RetryCount = $RetryCount\n            RetryIntervalSec = $RetryIntervalSec\n            DependsOn = \"[xADDomain]FirstDS\"\n        } \n#>\n\n        Script xWaitForADDomain_Alternative\n        {\n            GetScript = {\n                Return @{\n                    Result = [string]$(([ADSI]\"LDAP://$Using:DomainName\").distinguishedName)\n                }\n            }\n            TestScript = {\n                $DN = \"DC=$($Using:DomainName -replace '\\.',',DC=')\"\n                $FoundDomain = $false\n                For ($i=1;$i -le $Using:RetryCount;$i++) {\n                    If (([ADSI]\"LDAP://$DN\").distinguishedName -eq $DN) {\n                        $FoundDomain = $true\n                        Write-Verbose \"Found domain $($Using:DomainName).\"\n                        break\n                    } Else {\n                        Write-Verbose \"Could not find domain $($Using:DomainName). Attempt $i/$($Using:RetryCount). Sleeping $($Using:RetryIntervalSec) seconds...\"\n                        Start-Sleep -Seconds $Using:RetryIntervalSec\n                    }\n                }\n                Return $FoundDomain\n            }\n            SetScript = {\n                Write-Verbose 'Cannot continue. Domain not found.'\n                Throw \"Could not find domain $($Using:DomainName).\"\n            }\n        }\n\n        xADRecycleBin RecycleBin\n        {\n           EnterpriseAdministratorCredential = $DomainCreds\n           ForestFQDN = $DomainName\n           #DependsOn = '[xWaitForADDomain]DscForestWait'\n           DependsOn = '[Script]xWaitForADDomain_Alternative'\n        }\n\n\n        ### OUs ###\n        $DomainRoot = \"DC=$($DomainName -replace '\\.',',DC=')\"\n        $DependsOn_OU = @()\n\n        ForEach ($RootOU in $ConfigurationData.NonNodeData.RootOUs) {\n\n            xADOrganizationalUnit \"OU_$RootOU\"\n            {\n                Name = $RootOU\n                Path = $DomainRoot\n                ProtectedFromAccidentalDeletion = $true\n                Description = \"OU for $RootOU\"\n                Credential = $DomainCred\n                Ensure = 'Present'\n                DependsOn = '[xADRecycleBin]RecycleBin'\n            }\n\n            ForEach ($ChildOU in $ConfigurationData.NonNodeData.ChildOUs) {\n                \n                xADOrganizationalUnit \"OU_$($RootOU)_$ChildOU\"\n                {\n                    Name = $ChildOU\n                    Path = \"OU=$RootOU,$DomainRoot\"\n                    ProtectedFromAccidentalDeletion = $true\n                    Credential = $DomainCred\n                    Ensure = 'Present'\n                    DependsOn = \"[xADOrganizationalUnit]OU_$RootOU\"\n                }\n\n                $DependsOn_OU += \"[xADOrganizationalUnit]OU_$($RootOU)_$ChildOU\"\n            }\n\n        }\n\n\n        ### USERS ###\n        # Use PasswordAuthentication = 'Negotiate' to avoid the password verification failure once ADCS is installed.\n        # https://github.com/PowerShell/xActiveDirectory/issues/61\n        $DependsOn_User = @()\n        $Users = $ConfigurationData.NonNodeData.UserData | ConvertFrom-CSV\n        ForEach ($User in $Users) {\n\n            xADUser \"NewADUser_$($User.UserName)\"\n            {\n                DomainName = $DomainName\n                Ensure = 'Present'\n                UserName = $User.UserName\n                Path = \"OU=Users,OU=$($User.Dept),$DomainRoot\"\n                Enabled = $true\n                PasswordAuthentication = 'Negotiate'\n                Password = New-Object -TypeName PSCredential -ArgumentList 'JustPassword', (ConvertTo-SecureString -String $User.Password -AsPlainText -Force)\n                DependsOn = $DependsOn_OU\n            }\n            $DependsOn_User += \"[xADUser]NewADUser_$($User.UserName)\"\n        }\n\n        ### GROUPS ###\n        ForEach ($RootOU in $ConfigurationData.NonNodeData.RootOUs) {\n            xADGroup \"NewADGroup_$RootOU\"\n            {\n                GroupName = \"G_$RootOU\"\n                GroupScope = 'Global'\n                Description = \"Global group for $RootOU\"\n                Category = 'Security'\n                Members = ($Users | Where-Object {$_.Dept -eq $RootOU}).UserName\n                Path = \"OU=Groups,OU=$RootOU,$DomainRoot\"\n                Ensure = 'Present'\n                DependsOn = $DependsOn_User\n            }\n        }\n\n\n        WindowsFeature ADCS-Cert-Authority\n        {\n            Ensure = 'Present'\n            Name = 'ADCS-Cert-Authority'\n            DependsOn = '[xADRecycleBin]RecycleBin'\n        }\n\n        WindowsFeature ADCS-Web-Enrollment\n        {\n            Ensure = 'Present'\n            Name = 'ADCS-Web-Enrollment'\n            DependsOn = '[xADRecycleBin]RecycleBin'\n        }\n\n        WindowsFeature RSAT-ADCS\n        {\n            Ensure = 'Present'\n            Name = 'RSAT-ADCS'\n            DependsOn = '[xADRecycleBin]RecycleBin'\n        }\n\n        xADCSCertificationAuthority ADCS\n        {\n            Ensure = 'Present'\n            Credential = $DomainCreds\n            CAType = 'EnterpriseRootCA'\n            DependsOn = '[WindowsFeature]ADCS-Cert-Authority'              \n        }\n\n        xADCSWebEnrollment CertSrv\n        {\n            IsSingleInstance = 'Yes'\n            Ensure = 'Present'\n            Credential = $DomainCreds\n            DependsOn = '[xADCSCertificationAuthority]ADCS'\n        }\n\n        ADCSTemplate PSDSCEncryptionTemplate\n        {\n            Ensure = 'Present'\n            DisplayName = 'PSCMS'\n            JSON = $ConfigurationData.NonNodeData.JSON_PSCMS\n            Publish = $true\n            Identity = \"$DomainName\\Domain Computers\", \"$DomainName\\Domain Controllers\"\n            AutoEnroll = $true\n            PsDscRunAsCredential = $DomainCreds\n            DependsOn = '[xADCSWebEnrollment]CertSrv'\n        }\n\n        ADCSTemplate TaniumTemplate\n        {\n            Ensure = 'Present'\n            DisplayName = 'Tanium'\n            JSON = $ConfigurationData.NonNodeData.JSON_Tanium\n            Publish = $true\n            Identity = \"$DomainName\\Domain Computers\"\n            AutoEnroll = $false\n            PsDscRunAsCredential = $DomainCreds\n            DependsOn = '[xADCSWebEnrollment]CertSrv'\n        }\n\n    }\n}\n\n\n$configData = @{\n    AllNodes = @(\n        @{\n            Nodename = \"localhost\"\n            PSDscAllowPlainTextPassword = $true\n            PSDscAllowDomainUser = $true\n            Credential = $cred\n        }\n    )\n    NonNodeData = @{\n        \n        UserData = @'\nUserName,Password,Dept\nTaniumAdmin,P@ssw0rd,Tanium\nTaniumService,P@ssw0rd,Tanium\n'@\n        RootOUs = 'Tanium'\n        ChildOUs = 'Users','Groups'\n\n        JSON_PSCMS = @'\n{\n    \"name\":  \"PowerShellCMS\",\n    \"displayName\":  \"PowerShellCMS\",\n    \"objectClass\":  \"pKICertificateTemplate\",\n    \"flags\":  131680,\n    \"revision\":  100,\n    \"msPKI-Cert-Template-OID\":  \"1.3.6.1.4.1.311.21.8.14606814.4579994.15679635.15482926.4928991.141.63412935.14964662\",\n    \"msPKI-Certificate-Application-Policy\":  [\n                                                 \"1.3.6.1.4.1.311.80.1\"\n                                             ],\n    \"msPKI-Certificate-Name-Flag\":  268435456,\n    \"msPKI-Enrollment-Flag\":  32,\n    \"msPKI-Minimal-Key-Size\":  2048,\n    \"msPKI-Private-Key-Flag\":  16842752,\n    \"msPKI-RA-Signature\":  0,\n    \"msPKI-Template-Minor-Revision\":  1,\n    \"msPKI-Template-Schema-Version\":  2,\n    \"pKICriticalExtensions\":  [\n                                  \"2.5.29.15\"\n                              ],\n    \"pKIDefaultCSPs\":  [\n                           \"1,Microsoft RSA SChannel Cryptographic Provider\"\n                       ],\n    \"pKIDefaultKeySpec\":  1,\n    \"pKIExpirationPeriod\":  [\n                                0,\n                                128,\n                                114,\n                                14,\n                                93,\n                                194,\n                                253,\n                                255\n                            ],\n    \"pKIExtendedKeyUsage\":  [\n                                \"1.3.6.1.4.1.311.80.1\"\n                            ],\n    \"pKIKeyUsage\":  [\n                        32\n                    ],\n    \"pKIMaxIssuingDepth\":  0,\n    \"pKIOverlapPeriod\":  [\n                             0,\n                             128,\n                             166,\n                             10,\n                             255,\n                             222,\n                             255,\n                             255\n                         ]\n}\n'@\n\n        JSON_Tanium = @'\n{\n    \"name\":  \"Tanium\",\n    \"displayName\":  \"Tanium\",\n    \"objectClass\":  \"pKICertificateTemplate\",\n    \"flags\":  131649,\n    \"revision\":  100,\n    \"msPKI-Cert-Template-OID\":  \"1.3.6.1.4.1.311.21.8.14606814.4579994.15679635.15482926.4928991.141.13175610.2217120\",\n    \"msPKI-Certificate-Application-Policy\":  [\n                                                 \"1.3.6.1.5.5.7.3.1\",\n                                                 \"1.3.6.1.5.5.7.3.2\"\n                                             ],\n    \"msPKI-Certificate-Name-Flag\":  1,\n    \"msPKI-Enrollment-Flag\":  0,\n    \"msPKI-Minimal-Key-Size\":  2048,\n    \"msPKI-Private-Key-Flag\":  16842768,\n    \"msPKI-RA-Signature\":  0,\n    \"msPKI-Template-Minor-Revision\":  2,\n    \"msPKI-Template-Schema-Version\":  2,\n    \"pKICriticalExtensions\":  [\n                                  \"2.5.29.7\",\n                                  \"2.5.29.15\"\n                              ],\n    \"pKIDefaultKeySpec\":  1,\n    \"pKIExpirationPeriod\":  [\n                                0,\n                                128,\n                                114,\n                                14,\n                                93,\n                                194,\n                                253,\n                                255\n                            ],\n    \"pKIExtendedKeyUsage\":  [\n                                \"1.3.6.1.5.5.7.3.1\",\n                                \"1.3.6.1.5.5.7.3.2\"\n                            ],\n    \"pKIKeyUsage\":  [\n                        160,\n                        0\n                    ],\n    \"pKIMaxIssuingDepth\":  0,\n    \"pKIOverlapPeriod\":  [\n                             0,\n                             128,\n                             166,\n                             10,\n                             255,\n                             222,\n                             255,\n                             255\n                         ]\n}\n'@\n    }\n}\n\n\n\n#Install-Module -Name xAdcsDeployment, xActiveDirectory -Force\n#Get-DscResource | Sort-Object ModuleName, Version, Name\n\nmd C:\\ADCS -ErrorAction SilentlyContinue\ncd C:\\ADCS\n\n$cred = New-Object -TypeName PSCredential -ArgumentList 'Administrator', (ConvertTo-SecureString -String 'Passw0rd' -AsPlainText -Force)\n\nCreateADDomainWithCS -ConfigurationData $configData -DomainName 'goatee.lab' -AdminCreds $cred\n\nSet-DscLocalConfigurationManager -Path .\\CreateADDomainWithCS -Verbose\nStart-DscConfiguration -Path .\\CreateADDomainWithCS -Force -Verbose -Wait\n\n\nbreak\n\n\n#region CERT REQUEST/INSTALL ##################################################\n\ndir Cert:\\LocalMachine\\My\ndir Cert:\\LocalMachine\\My | Select-Object Thumbprint,Subject,@{name='KeyUsage';expression={$_.Extensions.KeyUsages}} | fl *\n\ncertutil -pulse\n\n$Req = @{\n    Template          = 'PSCMS'\n    Url               = 'ldap:'\n    CertStoreLocation = 'Cert:\\LocalMachine\\My'\n}\nGet-Certificate @Req\n\ndir Cert:\\LocalMachine\\My | Select-Object Thumbprint,Subject,@{name='KeyUsage';expression={$_.Extensions.KeyUsages}} | fl *\n\n$DocEncrCert = (dir Cert:\\LocalMachine\\My -DocumentEncryptionCert)[-1]\nProtect-CmsMessage -To $DocEncrCert -Content \"Encrypted with my new cert from the new template!\"\n\n#endregion ####################################################################\n\n\n"
  },
  {
    "path": "ansible/roles/vulns/adcs_templates/files/ADCSTemplate/Examples/Demo.ps1",
    "content": "﻿break\r\n\r\nGet-Module -ListAvailable\r\nImport-Module ADCSTemplate\r\nGet-Command -Module ADCSTemplate\r\n\r\n# Manually open ADSIEDIT and show objects\r\nadsiedit.msc\r\n\r\n# Manually open MMC to build and browse an AD CS mgmt GUI\r\nmmc\r\n\r\nNew-ADCSDrive\r\ncd ADCS:\r\ndir\r\ncd '.\\CN=Certificate Templates'\r\ndir\r\ncd ..\r\ncd '.\\CN=Enrollment Services'\r\ndir\r\ncd c:\r\n\r\ncd \\\r\nmd ADCS\r\ncd ADCS\r\n\r\nGet-ADCSTemplate\r\nGet-ADCSTemplate | Sort-Object DisplayName | ft DisplayName\r\n\r\nExport-ADCSTemplate -DisplayName PSCMS\r\nExport-ADCSTemplate -DisplayName PSCMS > PSCMS.json\r\n\r\nNew-ADCSTemplate -DisplayName PSCMS2 -JSON (Get-Content .\\PSCMS.json -Raw) -Publish\r\n\r\nSet-ADCSTemplateACL -DisplayName PSCMS2 -Identity 'goatee\\domain computers' -Enroll -AutoEnroll\r\n(Get-ADCSTemplate pscms2).nTSecurityDescriptor.Access\r\n\r\nRemove-ADCSTemplate -DisplayName pscms2 -WhatIf\r\nRemove-ADCSTemplate -DisplayName pscms2\r\nRemove-ADCSTemplate -DisplayName Tanium\r\n"
  },
  {
    "path": "ansible/roles/vulns/adcs_templates/files/ADCSTemplate/LICENSE",
    "content": "MIT License\n\nCopyright (c) 2018 Ashley McGlone\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "ansible/roles/vulns/adcs_templates/files/ADCSTemplate/README.md",
    "content": "Find all code and samples at this location: [https://github.com/GoateePFE/ADCSTemplate/]()\n\n# ADCSTemplate\nA PowerShell module for exporting, importing, removing, permissioning, publishing Active Directory Certificate Templates.\nIt also includes a DSC resource for creating AD CS templates using these functions.\nThis was built with the intent of using DSC for rapid lab builds, \nbut it could also be used in production environments to move templates between AD CS environments.\n\n# Problem\nAren't you tired of using the Active Directory Certificate Services graphical interface to create and publish new certificate templates? Me too! I can build a domain controller and certificate server with DSC, but then I get stuck with manually creating the custom certificate templates for my environment. A popular example is the Document Encryption certificate used for DSC credential encryption and the CMS encryption cmdlets. You probably have some custom certificate templates unique to your company as well. No more right click, duplicate, permission, publish!\n\n# Solution\nThe ADCSTemplate module contains the following PowerShell functions:\n* Export-ADCSTemplate\n* Get-ADCSTemplate\n* New-ADCSDrive\n* New-ADCSTemplate\n* Remove-ADCSTemplate\n* Set-ADCSTemplateACL\n\nAnd the following DSC resource:\n* ADCSTemplate\n\n# Overview\nThis is a simple outline of the procedure to export and import your templates.\nYes, you must create it manually at least once.\n1. Create your desired template in the AD CS GUI.\n2. `Install-Module ADCSTemplate`\n3. `Export-ADCSTemplate -DisplayName foo > .\\foo.json`\n4. Copy the JSON file to your destination environment.\n5. `Install-Module ADCSTemplate`\n6. `New-ADCSTemplate -DisplayName foo2 -JSON (Get-Content .\\foo.json -Raw) -Publish -Identity Contoso\\MyGroup`\n7. -OR- Use the `ADCSTemplate` DSC Resource with the JSON string data to define the template. This is most easily accomplished using a ConfigurationData block to pass the large string. See the sample provided.\n\nIf you want to duplicate an existing template on the same server try this:\n\n```New-ADCSTemplate -DisplayName NewTemplateName -JSON (Export-ADCSTemplate -DisplayName OldTemplateName)```\n\nIf you want to export all templates try this:\n\n``` (Get-ADCSTemplate).name | ForEach-Object {\"Exporting $_\"; Export-ADCSTemplate -DisplayName $_ | Out-File .\\$_.json -Force}```\n\nSee the module function help texts for many clever use cases for this code, including a bonus function for creating a PSDrive to browse the objects in AD without using the GUI.\n\nSee the \\Examples directory for\n* `Demo.ps1` showing popular use cases of the functions together.\n* `Build-ADCS.ps1` DSC example for a full Active Directory domain controller build with Certificate Services and two sample templates.\n* `PowerShellCMS.json` a sample JSON output file you can use to create templates for PowerShell Cryptographic Message Syntax cmdlets and encryption credentials in DSC.\n\n# Requirements\n* PowerShell 5.x\n* Tested on Windows Server 2012 R2\n* Tested on Windows Server 2016 (issues with the xActiveDirectory module here, but the ADCSTemplate DSC works just fine)\n* Enterprise Administrator rights\n\n# Credits\nCreated by Ashley McGlone\n\n2017-2018\n\n[@GoateePFE](https://twitter.com/goateepfe)\n\n[http://aka.ms/goateepfe]()\n\n\n# Get-Help\n\n## Export-ADCSTemplate\n\n### Synopsis\nReturns a JSON string with the properties of an Active Directory certificate template.\n\n### Description\nReturns a JSON string with the properties of an Active Directory certificate template.\nBy default returns only the PKI-related properties of the object. These properties are\nsufficient for passing to the New-ADCSTemplate function.\n\n### Parameters\n\n-DisplayName <String>\n    DisplayName for the certificate to export.\n    \n    Required?                    true\n    Position?                    1\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    2\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Detailed [<SwitchParameter>]\n    Includes all ADObject properties of the template. These are not required for \n    use with the New-ADCSTemplate function.\n    \n    Required?                    false\n    Position?                    named\n    Default value                False\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nC.R.U.D. AD CS Template Operations in this module.\nNo longer have to use the cert GUI to clone a template and build a new one.\nCreate one manually the first time in the GUI, then export it to JSON.\nPass the JSON in your new environment (file, here string, DSC, etc.) to build from scratch.\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> Export-ADCSTemplate -DisplayName PowerShellCMS\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> Export-ADCSTemplate -DisplayName PowerShellCMS -Detailed\n\n```\n-------------------------- EXAMPLE 3 --------------------------\n\n```\nPS C:\\> ### Backup all the templates to JSON\nmd C:\\ADCSTemplates -ErrorAction SilentlyContinue\ncd C:\\ADCSTemplates\n(Get-ADCSTemplate).name | ForEach-Object {\"Exporting $_\"; Export-ADCSTemplate -DisplayName $_ | Out-File .\\$_.json -Force}\ndir\n\n```\n-------------------------- EXAMPLE 4 --------------------------\n\n```\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS-NEW -JSON (Export-ADCSTemplate -DisplayName PowerShellCMS-OLD)\n\n```\n\n## Get-ADCSTemplate\n\n### Synopsis\nReturns the properties of either a single or all Active Directory Certificate Template(s).\n\n### Description\nReturns the properties of either a single or list of Active Directory Certificate Template(s)\ndepending on whether a DisplayName parameter was passed.\n\n### Parameters\n\n-DisplayName <String>\n    Name of an AD CS template to retrieve.\n    \n    Required?                    false\n    Position?                    1\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    named\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> Get-ADCSTemplate\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> Get-ADCSTemplate -DisplayName PowerShellCMS\n\n```\n-------------------------- EXAMPLE 3 --------------------------\n\n```\nPS C:\\> Get-ADCSTemplate | Sort-Object Name | ft Name, Created, Modified\n\n```\n-------------------------- EXAMPLE 4 --------------------------\n\n```\nPS C:\\> ###View template permissions\n(Get-ADCSTemplate pscms).nTSecurityDescriptor\n(Get-ADCSTemplate pscms).nTSecurityDescriptor.Sddl\n(Get-ADCSTemplate pscms).nTSecurityDescriptor.Access\nConvertFrom-SddlString -Sddl (Get-ADCSTemplate pscms).nTSecurityDescriptor.sddl -Type ActiveDirectoryRights\n\n```\n\n## New-ADCSDrive\n\n### Synopsis\nMaps a PowerShell drive to the Active Directory Certificate Services location.\n\n### Description\nMaps a PowerShell drive to the Active Directory Certificate Services location \nof the Configuration partition under CN=Public Key Services,CN=Services,... .\nThe new drive is ADCS:. This is purely for convenience of checking the objects\nupdated by functions in the ADCSTemplate module.\n\n### Parameters\n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    1\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> New-ADCSDrive\nPS C:\\> Set-Location ADCS:\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> ### Explore templates with drive\nNew-ADCSDrive\nGet-PSDrive\ncd ADCS:\ndir\n\n# List templates\ncd '.\\CN=Certificate Templates'\ndir\ndir | fl *\ndir *WebServer*\n\n# list CAs\ncd \\\ncd '.\\CN=Enrollment Services'\ndir\ncd C:\n\n```\n\n## New-ADCSTemplate\n\n### Synopsis\nCreates a new Active Directory Certificate Services template based on a JSON export.\n\n### Description\nCreates a new Active Directory Certificate Services template based on a JSON export.\nOptionally can permission and publish the template (best practice).\n\n### Parameters\n\n-DisplayName <String>\n    DisplayName for the certificate template to create. This does not have to match\n    the original name of the exported template.\n    \n    Required?                    true\n    Position?                    1\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-JSON <String>\n    JSON string output from Export-ADCSTemplate. Defines the template to create.\n    Can be retrieved from file using Get-Content -Raw.\n    \n    Required?                    true\n    Position?                    2\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    3\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Identity <String[]>\n    String or string array of Active Directory identities (users or groups).\n    This is optional for permissioning the template.\n    \n    Required?                    false\n    Position?                    4\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-AutoEnroll [<SwitchParameter>]\n    Default permission is Read and Enroll. Use this switch to also grant AutoEnroll \n    to the identity. Only used when Identity parameter is used.\n    \n    Required?                    false\n    Position?                    named\n    Default value                False\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Publish [<SwitchParameter>]\n    Publish the template to *ALL* Certificate Authority issuers. Use with caution\n    in production environments. You may want to manually publish to only specific\n    Certificate Authorities in production. In a lab this is ideal.\n    \n    Required?                    false\n    Position?                    named\n    Default value                False\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nThis function does not use the official (complicated) API for PKI management.\nInstead it creates the exact same AD objects that are generated by the API,\nincluding AD forest-specific OIDs.\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS -JSON (Get-Content .\\pscms.json -Raw)\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS -JSON (Get-Content .\\pscms.json -Raw) -Server dc1.contoso.com -Identity G_DSCNodes -AutoEnroll -Publish\n# From a client configured for AD CS autoenrollment:\n$Req = @{\n    Template          = 'PowerShellCMS'\n    Url               = 'ldap:'\n    CertStoreLocation = 'Cert:\\LocalMachine\\My'\n}\nGet-Certificate @Req\n# Note: If you have the Carbon module installed, it conflicts with Get-Certificate native cmdlet.\n\n$DocEncrCert = (dir Cert:\\LocalMachine\\My -DocumentEncryptionCert | Sort-Object NotBefore)[-1]\nProtect-CmsMessage -To $DocEncrCert -Content \"Encrypted with my new cert from the new template!\"\n\n```\n-------------------------- EXAMPLE 3 --------------------------\n\n```\nPS C:\\> New-ADCSTemplate -DisplayName PowerShellCMS-NEW -JSON (Export-ADCSTemplate -DisplayName PowerShellCMS-OLD)\n\n```\n\n## Remove-ADCSTemplate\n\n### Synopsis\nRemoves a certificate template from Active Directory.\n\n### Description\nRemoves the template from any issuers where it is published.\nRemoves the template itself.\nRemoves the unique OID object of the template.\n\n### Parameters\n\n-DisplayName <String>\n    DisplayName for the certificate template to delete.\n    \n    Required?                    true\n    Position?                    1\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    2\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-WhatIf [<SwitchParameter>]\n    \n    Required?                    false\n    Position?                    named\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Confirm [<SwitchParameter>]\n    \n    Required?                    false\n    Position?                    named\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nUse with caution!\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> Remove-ADCSTemplate -DisplayName PowerShellCMS\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> (Get-ADCSTemplate).name | Where-Object {$_ -like \"PowerShellCMS*\"} | ForEach-Object {Remove-ADCSTemplate -DisplayName $_ -Verbose}\n\n```\n\n## Set-ADCSTemplateACL\n\n### Synopsis\nAdds an ACL to an Active Directory Certificate template.\n\n### Description\nAdds an ACL to an Active Directory Certificate template.\nDefault permission is read (without the Enroll or AutoEnroll switches).\n\n### Parameters\n\n-DisplayName <String>\n    Name of an AD CS template to receive the ACL.\n    \n    Required?                    true\n    Position?                    1\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Server <String>\n    FQDN of Active Directory Domain Controller to target for the operation.\n    When not specified it will search for the nearest Domain Controller.\n    \n    Required?                    false\n    Position?                    2\n    Default value                (Get-ADDomainController -Discover -ForceDiscover -Writable).HostName[0]\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Type <String>\n    ACL type: Allow or Deny\n    \n    Required?                    false\n    Position?                    3\n    Default value                Allow\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Identity <String[]>\n    String or string array of Active Directory identities (users or groups)\n    \n    Required?                    false\n    Position?                    4\n    Default value                \n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-Enroll [<SwitchParameter>]\n    Set the Enroll permission\n    \n    Required?                    false\n    Position?                    named\n    Default value                False\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n-AutoEnroll [<SwitchParameter>]\n    Set the AutoEnroll permission\n    \n    Required?                    false\n    Position?                    named\n    Default value                False\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n    \n\n### Notes\nRequires Enterprise Administrator permissions, since this touches the AD Configuration partition.\n\n### Examples\n-------------------------- EXAMPLE 1 --------------------------\n\n```\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Allow -Identity 'CONTOSO\\Servers Group' -Enroll\n\n```\n-------------------------- EXAMPLE 2 --------------------------\n\n```\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Allow -Identity 'CONTOSO\\Servers Group','CONTOSO\\Workstations Group' -Enroll -AutoEnroll\n\n```\n-------------------------- EXAMPLE 3 --------------------------\n\n```\nPS C:\\> Set-ADCSTemplateACL -DisplayName PowerShellCMS -Type Deny -Identity 'CONTOSO\\Servers Group'\n\n```\n"
  },
  {
    "path": "ansible/roles/vulns/adcs_templates/tasks/main.yml",
    "content": "- name: Refresh\n  ansible.windows.win_command: gpupdate /force\n\n- name: Install ADCSTemplate Module\n  win_copy:\n    src: files/ADCSTemplate\n    dest: \"C:\\\\Program Files\\\\WindowsPowerShell\\\\Modules\"\n\n- name: create a directory for templates\n  win_file: \n    path: c:\\setup\n    state: directory\n\n- name: Install templates\n  win_shell: |\n    if (-not(Get-ADCSTemplate -DisplayName \"{{item.value.template_name}}\")) { New-ADCSTemplate -DisplayName \"{{item.value.template_name}}\" -JSON (Get-Content {{item.value.template_file}} -Raw) -Identity \"{{domain_name}}\\Domain Users\" -Publish }\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    domain_name: \"{{domain}}\"\n    ansible_become_user: \"{{domain_username}}\"\n    ansible_become_password: \"{{domain_password}}\"\n  with_dict: \"{{ vulns_vars }}\""
  },
  {
    "path": "ansible/roles/vulns/administrator_folder/tasks/main.yml",
    "content": "- name: \"Check if administrator folder already exist\"\n  ansible.windows.win_stat:\n    path: \"c:\\\\users\\\\administrator\"\n  register: administrator_folder\n\n- name: \"Check if administrator folder already exist\"\n  ansible.windows.win_stat:\n    path: \"c:\\\\users\\\\administrator\\\\desktop\"\n  register: administrator_desktop_folder\n\n- name: \"Create administrator directory\"\n  ansible.windows.win_file:\n    path: \"c:\\\\users\\\\administrator\"\n    state: directory\n  when: not administrator_folder.stat.exists\n\n- name: \"Create administrator desktop directory\"\n  ansible.windows.win_file:\n    path: \"c:\\\\users\\\\administrator\\\\desktop\"\n    state: directory\n  when: not administrator_desktop_folder.stat.exists\n\n- name: Disable inherited ACE's\n  ansible.windows.win_acl_inheritance:\n    path: \"c:\\\\users\\\\administrator\"\n    state: absent\n  when: not administrator_folder.stat.exists\n\n- name: \"Allow c:\\\\users\\\\administrator to administrators\"\n  ansible.windows.win_acl:\n    path: \"c:\\\\users\\\\administrator\"\n    user: Administrator\n    rights: Read,Write,Modify,FullControl,Delete\n    type: allow\n    state: present\n  when: not administrator_folder.stat.exists\n\n- name: \"Allow c:\\\\users\\\\administrator to administrators\"\n  ansible.windows.win_acl:\n    path: \"c:\\\\users\\\\administrator\"\n    user: NT AUTHORITY\\SYSTEM\n    rights: Read,Write,Modify,FullControl,Delete\n    type: allow\n    state: present\n  when: not administrator_folder.stat.exists\n\n- name: \"Allow c:\\\\users\\\\administrator to administrators\"\n  ansible.windows.win_acl:\n    path: \"c:\\\\users\\\\administrator\"\n    user: Administrators\n    rights: Read,Write,Modify,FullControl,Delete\n    type: allow\n    state: present\n  when: not administrator_folder.stat.exists"
  },
  {
    "path": "ansible/roles/vulns/autologon/tasks/main.yml",
    "content": "- name: Add windows autologon\n  community.windows.win_auto_logon:\n    username: \"{{item.value.username}}\"\n    password: \"{{item.value.password}}\"\n  with_dict: \"{{ vulns_vars }}\""
  },
  {
    "path": "ansible/roles/vulns/credentials/tasks/main.yml",
    "content": "- name: Store a password in Credential Manager\n  community.windows.win_credential:\n    name: \"{{item.key}}\"\n    type: domain_password\n    username: \"{{item.value.username}}\"\n    secret: \"{{item.value.secret}}\"\n    comment: \"Credential for {{item.value.username}}\"\n    persistence: local\n    state: present\n  ignore_errors: true\n  vars:\n    ansible_become: yes\n    ansible_become_method: runas\n    ansible_become_user: \"{{item.value.runas | default(domain_username) }}\"\n    ansible_become_password: \"{{item.value.runas_password | default(domain_password) }}\"\n  with_dict: \"{{ vulns_vars }}\""
  },
  {
    "path": "ansible/roles/vulns/directory/tasks/main.yml",
    "content": "- name: Create directory\n  ansible.windows.win_file:\n    path: \"{{item.value}}\"\n    state: directory\n  with_dict: \"{{ vulns_vars }}\""
  },
  {
    "path": "ansible/roles/vulns/disable_firewall/tasks/main.yml",
    "content": "- name: Disable Domain firewall\n  community.windows.win_firewall:\n    state: disabled\n    profiles:\n    - Domain\n    - Private\n    - Public\n  tags: disable_firewall"
  },
  {
    "path": "ansible/roles/vulns/enable_credssp_client/tasks/main.yml",
    "content": "- name: \"Enable wsman credssp \"\n  ansible.windows.win_shell:\n    Enable-WSManCredSSP -Role \"Client\" -DelegateComputer \"*\" -Force"
  },
  {
    "path": "ansible/roles/vulns/enable_credssp_server/tasks/main.yml",
    "content": "- name: \"Enable wsman credssp \"\n  ansible.windows.win_shell:\n    Enable-WSManCredSSP -Role Server -Force"
  },
  {
    "path": "ansible/roles/vulns/enable_llmnr/tasks/main.yml",
    "content": "- name: \"Enable LLMNR protocol\"\n  ansible.windows.win_powershell:\n    script: |\n      REG ADD  \"HKLM\\Software\\policies\\Microsoft\\Windows NT\\DNSClient\" /v \"EnableMulticast\" /t REG_DWORD /d \"1\" /f\n"
  },
  {
    "path": "ansible/roles/vulns/enable_nbt-ns/tasks/main.yml",
    "content": "- name: \"Enable NBT-NS protocol\"\n  ansible.windows.win_powershell:\n    script: |\n      $regkey = \"HKLM:SYSTEM\\CurrentControlSet\\services\\NetBT\\Parameters\\Interfaces\"\n      Get-ChildItem $regkey |foreach { Set-ItemProperty -Path \"$regkey\\$($_.pschildname)\" -Name NetbiosOptions -Value 0 -Verbose}\n"
  },
  {
    "path": "ansible/roles/vulns/files/tasks/main.yml",
    "content": "- name: Copy a single file\n  ansible.windows.win_copy:\n    src: \"../ad/{{domain_name}}/files/{{item.value.src}}\"\n    dest: \"{{item.value.dest}}\"\n  with_dict: \"{{ vulns_vars }}\""
  },
  {
    "path": "ansible/roles/vulns/mssql/tasks/main.yml",
    "content": "- name: Run SQL COMMAND\n  win_shell: |\n    SqlCmd -E {{item.value.cmd}}\n  with_dict: \"{{ vulns_vars }}\""
  },
  {
    "path": "ansible/roles/vulns/no_ldap_channel_binding/tasks/main.yml",
    "content": "# 0\tDisabled. LDAP channel binding tokens (CBT) are not required.\n# 1\tEnabled (optional). CBT is validated if present, but not required.\n# 2\tStrict enforcement. Clients must support channel binding; otherwise binds fail.\n- name: Disable LDAPS Channel Binding (LdapEnforceChannelBindings = 0)\n  ansible.windows.win_regedit:\n    path: HKLM:\\SYSTEM\\CurrentControlSet\\Services\\NTDS\\Parameters\n    name: LdapEnforceChannelBindings\n    type: dword\n    data: 0"
  },
  {
    "path": "ansible/roles/vulns/no_ldap_integrity/tasks/main.yml",
    "content": "#0\tNo signing required. The server will not require integrity protection for LDAP binds.\n#1\tSigning required for SASL (e.g., Kerberos/NTLM) binds only. Simple binds are allowed without signing.\n#2\tSigning required for all LDAP binds (simple and SASL). Simple binds over non-SSL connections will fail.\n\n- name: Disable LDAP Server Integrity (LDAPServerIntegrity = 0)\n  ansible.windows.win_regedit:\n    path: HKLM:\\SYSTEM\\CurrentControlSet\\Services\\NTDS\\Parameters\n    name: LDAPServerIntegrity\n    type: dword\n    data: 0"
  },
  {
    "path": "ansible/roles/vulns/no_ldap_signing/tasks/main.yml",
    "content": "# 0\tNone. The server does not require LDAP signing. Unsigned simple binds are allowed.\n# 1\tNegotiate signing. The server will request signing but allow unsigned binds if the client does not support signing.\n# 2\tRequire signing. All LDAP binds must be signed; unsigned simple binds are rejected.\n- name: Disable LDAP Signing (RequireSigning = 0)\n  ansible.windows.win_regedit:\n    path: HKLM:\\SYSTEM\\CurrentControlSet\\Services\\LDAP\n    name: LDAPServerSigningRequirements\n    type: dword\n    data: 0"
  },
  {
    "path": "ansible/roles/vulns/ntlmdowngrade/tasks/main.yml",
    "content": "# values : https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/network-security-lan-manager-authentication-level\n# NTLMv1 downgrade attacks are possible with LmCompatibilityLevel 2 and below\n- name: Enable LmCompatibilityLevel\n  win_regedit:\n    path: HKLM:\\System\\CurrentControlSet\\Control\\Lsa\n    name: LmCompatibilityLevel\n    data: 0x2\n    type: dword\n"
  },
  {
    "path": "ansible/roles/vulns/openshares/tasks/main.yml",
    "content": "# SMB share users only\n- name: Ensure directory structure for public share exists\n  win_file:\n    path: C:\\shares\\public\n    state: directory\n\n- name: Ensure public share exists\n  win_share:\n    name: public\n    description: Basic Read share for all domain users\n    path: C:\\shares\\public\n    list: yes\n    full: Administrators\n    change: Users\n\n# allow anonymous on win10 (https://docs.microsoft.com/fr-fr/troubleshoot/windows-server/networking/guest-access-in-smb2-is-disabled-by-default)\n\n- name: Add or update registry path to allow guest access in SMB\n  win_regedit:\n    path: HKLM:\\SYSTEM\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters\n    name: AllowInsecureGuestAuth\n    data: 1\n    type: dword\n\n# allow guest user\n- name: activate guest account\n  win_command: net user guest /active:yes\n\n# SMB share anonymous\n- name: Ensure directory structure for all share exists\n  win_file:\n    path: C:\\shares\\all\n    state: directory\n\n- name: Add all share everyone rights\n  win_acl:\n    path: C:\\shares\\all\n    user: Everyone\n    rights: FullControl\n    type: allow\n    state: present\n\n- name: all shares\n  win_share:\n    name: all\n    description: Basic RW share for all\n    path: C:\\shares\\all\n    list: yes\n    full: Everyone\n\n"
  },
  {
    "path": "ansible/roles/vulns/permissions/tasks/main.yml",
    "content": "# https://docs.ansible.com/ansible/latest/collections/ansible/windows/win_acl_module.html\n- name: change folder allow rights\n  ansible.windows.win_acl:\n    path: \"{{item.value.path}}\"\n    user: \"{{item.value.user}}\"\n    rights: \"{{item.value.rights}}\"\n    type: allow\n    state: present\n    inherit: ContainerInherit, ObjectInherit\n    propagation: 'None'\n  with_dict: \"{{ vulns_vars }}\"\n"
  },
  {
    "path": "ansible/roles/vulns/schedule/tasks/main.yml",
    "content": "# 0 will start a new instance in parallel with existing instances of that task.\n# 1 will wait until other instances of that task to finish running before starting itself.\n# 2 will not start a new instance if another is running.\n# 3 will stop other instances of the task and start the new one.\n# https://docs.ansible.com/ansible/latest/collections/community/windows/win_scheduled_task_module.html\n- name: Create a task that will be repeated every minute\n  community.windows.win_scheduled_task:\n    name: \"{{item.value.name}}\"\n    description: ansible schedule task\n    multiple_instances: \"{{ item.value.multiple_instances | default('2') }}\"\n    actions:\n    - path: cmd.exe\n      arguments: \"/c {{item.value.cmd}}\"\n    triggers:\n    - type: registration\n      repetition:\n        interval: \"{{item.value.interval}}\"\n    - type: boot\n      repetition:\n        interval: \"{{item.value.interval}}\"\n    username: SYSTEM\n  with_dict: \"{{ vulns_vars }}\""
  },
  {
    "path": "ansible/roles/vulns/shares/tasks/main.yml",
    "content": "# SMB share users only\n- name: Create directory if not exist\n  win_file:\n    path: \"{{item.value.path}}\"\n    state: directory\n  with_dict: \"{{ vulns_vars }}\"\n\n- name: Create share\n  ansible.windows.win_share:\n    name: \"{{item.key}}\"\n    description: \"{{item.value.description | default(item.key) }}\" \n    path: \"{{item.value.path}}\"\n    list: \"{{item.value.list| default('yes')}}\"\n    full: \"{{item.value.full| default('Administrators')}}\"\n    change: \"{{item.value.change| default('')}}\"\n    read: \"{{item.value.read| default('')}}\"\n    deny: \"{{item.value.deny| default('')}}\"\n  register: shareregister\n  with_dict: \"{{ vulns_vars }}\"\n\n# change permissions according to rights\n- include_tasks: perm.yml\n  vars:\n    path: \"{{item.value.path}}\"\n    users: \"{{ item.value.full | split(',') |trim | default([])  }}\"\n    perm: \"FullControl\"\n    type: \"allow\"\n  with_dict: \"{{ vulns_vars }}\"\n\n\n- include_tasks: perm.yml\n  vars:\n    path: \"{{item.value.path}}\"\n    users: \"{{ item.value.change | split(',') |trim | default([])  }}\"\n    perm: \" Read,Write,Modify,Delete\"\n    type: \"allow\"\n  with_dict: \"{{ vulns_vars }}\"\n\n- include_tasks: perm.yml\n  vars:\n    path: \"{{item.value.path}}\"\n    users: \"{{ item.value.read | split(',') |trim | default([])  }}\"\n    perm: \" Read\"\n    type: \"allow\"\n  with_dict: \"{{ vulns_vars }}\"\n\n- include_tasks: perm.yml\n  vars:\n    path: \"{{item.value.path}}\"\n    users: \"{{ item.value.deny | split(',') |trim | default([])  }}\"\n    perm: \"Read,Write,Modify,FullControl,Delete\"\n    type: \"deny\"\n  with_dict: \"{{ vulns_vars }}\"\n"
  },
  {
    "path": "ansible/roles/vulns/shares/tasks/perm.yml",
    "content": "- name: \"Add share folder users change {{type}} : {{perm}} rights\"\n  ansible.windows.win_acl:\n    path: \"{{path}}\"\n    user: \"{{share_user}}\"\n    rights: \"{{perm}}\"\n    type: \"{{type}}\"\n    state: present\n  loop: \"{{users}}\"\n  loop_control:\n    loop_var: share_user"
  },
  {
    "path": "ansible/roles/vulns/smbv1/tasks/main.yml",
    "content": "- name: Enable SMBV1 feature\n  win_feature:\n    name: SMB1Protocol\n    state: present\n    include_sub_features: yes\n    include_management_tools: yes\n  register: win_feature\n\n- name: Reboot if feature requires it\n  ansible.windows.win_reboot:\n  when: win_feature.reboot_required"
  },
  {
    "path": "ansible/roles/webdav/tasks/main.yml",
    "content": "- name: Ensure WebDAV client feature is installed\n  ansible.windows.win_feature:\n    name: WebDAV-Redirector\n    state: present\n  register: webdav_feature\n\n- name: Reboot after installing WebDAV client feature\n  ansible.windows.win_reboot:\n  when: webdav_feature.reboot_required"
  },
  {
    "path": "ansible/sccm-client.yml",
    "content": "- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n- name: \"client install\"\n  hosts: sccm\n  roles:\n    - { role: 'sccm/config/client_install', tags: 'sccm_client_install' }\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    sccm_server: \"{{lab.domains[domain].sccm.sccm_server | default('')}}\"\n    site_code: \"{{lab.domains[domain].sccm.site_code}}\"\n    clients: \"{{lab.domains[domain].sccm.clients| default([])}}\"\n"
  },
  {
    "path": "ansible/sccm-config.yml",
    "content": "- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n- name: \"Config SCCM\"\n  hosts: sccm\n  roles:\n    - { role: 'sccm/config/discovery', tags: 'sccm_discovery'}\n    - { role: 'sccm/config/boundary', tags: 'sccm_boundary'}\n    - { role: 'sccm/config/accounts', tags: 'sccm_accounts'}\n    - { role: 'sccm/config/client_push', tags: 'sccm_client_push'}\n    - { role: 'sccm/config/naa', tags: 'sccm_naa'}\n    - { role: 'sccm/config/client_install', tags: 'sccm_client_install'}\n    - { role: 'sccm/config/users', tags: 'sccm_users'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    sccm_server: \"{{lab.domains[domain].sccm.sccm_server | default('')}}\"\n    sccm_mssql_server: \"{{lab.domains[domain].sccm.sccm_mssql_server | default('')}}\"\n    site_code: \"{{lab.domains[domain].sccm.site_code}}\"\n    pxe_pass: \"{{lab.domains[domain].sccm.pxe_pass| default('')}}\"\n    clients: \"{{lab.domains[domain].sccm.clients| default([])}}\"\n    naa_user_name: \"{{lab.domains[domain].sccm.naa_user| default('')}}\"\n    naa_user: \"{{domain}}\\\\{{naa_user_name}}\"\n    naa_pass: \"{{lab.domains[domain].users[naa_user_name].password}}\"\n    push_account_name: \"{{lab.domains[domain].sccm.push_account| default('')}}\"\n    push_account: \"{{domain}}\\\\{{push_account_name}}\"\n    push_account_pass: \"{{lab.domains[domain].users[push_account_name].password}}\"\n    account_da_name: \"{{lab.domains[domain].sccm.account_da| default('')}}\"\n    account_da: \"{{domain}}\\\\{{account_da_name}}\"\n    account_da_pass: \"{{lab.domains[domain].users[account_da_name].password}}\"\n    admins: \"{{lab.domains[domain].sccm.admins}}\"\n    cma_users: {\n      push_account: {\n        name: \"{{push_account}}\",\n        password: \"{{push_account_pass}}\"\n      },\n      naa_user: {\n        name: \"{{naa_user}}\",\n        password: \"{{naa_pass}}\"\n      },\n      account_da: {\n        name: \"{{account_da}}\",\n        password: \"{{account_da_pass}}\"\n      }\n    }\n"
  },
  {
    "path": "ansible/sccm-install.yml",
    "content": "- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n- name: \"Setup Prerequisites\"\n  hosts: dc\n  roles:\n    - { role: 'sccm/install/prerequistes', tags: 'sccm_prerequistes', when: sccm_server != ''}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    site_code: \"{{lab.domains[domain].sccm.site_code}}\"\n    sccm_server: \"{{lab.domains[domain].sccm.sccm_server | default('')}}\"\n    sccm_mssql_server: \"{{lab.domains[domain].sccm.sccm_mssql_server | default('')}}\"\n\n- name: \"Install SCCM\"\n  hosts: sccm\n  roles:\n    - { role: 'sccm/install/iis', tags: 'sccm_iis'}\n    - { role: 'sccm/install/adk', tags: 'sccm_adk'}\n#    - { role: 'sccm/mssql', tags: 'sccm_wsus', when: sccm_server != ''} # done by the server playbook\n    - { role: 'sccm/install/wsus', tags: 'sccm_wsus'}\n    - { role: 'sccm/install/mecm', tags: 'sccm_mecm'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    site_code: \"{{lab.domains[domain].sccm.site_code}}\"\n    sccm_server: \"{{lab.domains[domain].sccm.sccm_server | default('')}}\"\n    sccm_mssql_server: \"{{lab.domains[domain].sccm.sccm_mssql_server | default('')}}\"\n"
  },
  {
    "path": "ansible/sccm-pxe.yml",
    "content": "- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n- name: \"Setup SCCM PXE\"\n  hosts: sccm\n  roles:\n    - { role: 'sccm/config/pxe', tags: 'sccm_pxe'}\n    - { role: 'sccm/pxe', tags: 'sccm_pxe' }\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    site_code: \"{{lab.domains[domain].sccm.site_code}}\"\n    pxe_pass: \"{{lab.domains[domain].sccm.pxe_pass| default('')}}\"\n    sccm_server: \"{{lab.domains[domain].sccm.sccm_server | default('')}}\"\n    admin_pass: \"{{lab.domains[domain].sccm.pxe_admin_pass}}\"\n    ou_location: \"{{lab.domains[domain].sccm.pxe_location}}\"\n    naa_user_name: \"{{lab.domains[domain].sccm.naa_user| default('')}}\"\n    naa_user: \"{{domain}}\\\\{{naa_user_name}}\"\n    naa_pass: \"{{lab.domains[domain].users[naa_user_name].password}}\"\n\n"
  },
  {
    "path": "ansible/security.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n- name: \"Setup enable defender\"\n  hosts: defender_on\n  roles:\n    - { role: 'settings/windows_defender', tags: 'windows_defender', windows_defender_status: 'on' }\n  vars:\n    script_path: \"../ad/{{domain_name}}/scripts\"\n\n- name: Setup disable defender\n  hosts: defender_off\n  roles:\n    - { role: 'settings/windows_defender', tags: 'windows_defender', windows_defender_status: 'off' }\n  vars:\n    script_path: \"../ad/{{domain_name}}/scripts\"\n\n- name: \"Setup security with tasks\"\n  hosts: domain\n  tasks:\n    - include_role:\n        name: \"security/{{secu}}\"\n      vars:\n        security_vars : \"{{ lab.hosts[dict_key].security_vars[secu] | default({}) }}\"\n        domain: \"{{lab.hosts[dict_key].domain}}\"\n        domain_username: \"{{domain}}\\\\{{admin_user}}\"\n        domain_password: \"{{lab.domains[domain].domain_password}}\"\n      loop: \"{{lab.hosts[dict_key].security | default([]) }}\"\n      loop_control:\n        loop_var: secu"
  },
  {
    "path": "ansible/servers.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n- name: \"Install IIS\"\n  hosts: iis\n  roles:\n    - { role: 'iis', tags: 'iis'}\n\n- name: \"Install MSSQL Express\"\n  hosts: mssql\n  serial: 1 # add one MSSQL install at a time to avoid issues\n  roles:\n    - { role: 'mssql', tags: 'mssql'}\n    - { role: 'mssql_link', tags: 'mssql, mssql_link'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    SQLSVCACCOUNT_NAME: \"{{lab.hosts[dict_key].mssql.svcaccount| default('NT AUTHORITY\\\\NETWORK SERVICE')}}\"\n    SQLSVCACCOUNT_NAMEDOMAIN: \"{{domain}}\\\\{{SQLSVCACCOUNT_NAME}}\"\n    SQLSVCACCOUNT: \"{{SQLSVCACCOUNT_NAME if SQLSVCACCOUNT_NAME == 'NT AUTHORITY\\\\NETWORK SERVICE' else SQLSVCACCOUNT_NAMEDOMAIN }}\"\n    SQLSVCPASSWORD: \"{{lab.domains[domain].users[SQLSVCACCOUNT_NAME].password| default('')}}\"\n    SQLYSADMIN: \"{{SQLSVCACCOUNT}}\"\n    domain_admin: \"{{domain}}\\\\{{admin_user}}\"\n    domain_admin_password: \"{{lab.domains[domain].domain_password}}\"\n    sql_sysadmins: \"{{lab.hosts[dict_key].mssql.sysadmins | default([]) }}\"\n    executeaslogin: \"{{lab.hosts[dict_key].mssql.executeaslogin  | default({}) }}\"\n    executeasuser:  \"{{lab.hosts[dict_key].mssql.executeasuser | default({}) }}\"\n    sa_password: \"{{lab.hosts[dict_key].mssql.sa_password}}\"\n    linked_servers: \"{{lab.hosts[dict_key].mssql.linked_servers | default({}) }}\"\n\n- name: \"Install SQL Server Management Studio\"\n  hosts: mssql_ssms\n  roles:\n    - { role: 'mssql_ssms', tags: 'mssql_ssms'}\n\n- name: \"Install SQL Server reporting\"\n  hosts: mssql_reporting\n  roles:\n    - { role: 'mssql_reporting', tags: 'mssql_reporting'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_admin: \"{{domain}}\\\\{{admin_user}}\"\n    domain_admin_password: \"{{lab.domains[domain].domain_password}}\"\n\n- name: \"Install Webdav\"\n  hosts: webdav\n  roles:\n    - { role: 'webdav', tags: 'webdav'}"
  },
  {
    "path": "ansible/vulnerabilities.yml",
    "content": "---\n# Load datas\n- import_playbook: data.yml\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n- name: \"Setup vulnerabilities with tasks\"\n  hosts: domain\n  tasks:\n    - include_role:\n        name: \"vulns/{{vuln}}\"\n      vars:\n        vulns_vars : \"{{ lab.hosts[dict_key].vulns_vars[vuln] | default({}) }}\"\n        domain: \"{{lab.hosts[dict_key].domain}}\"\n        domain_username: \"{{domain}}\\\\{{admin_user}}\"\n        domain_password: \"{{lab.domains[domain].domain_password}}\"\n      loop: \"{{lab.hosts[dict_key].vulns | default([]) }}\"\n      loop_control:\n        loop_var: vuln\n\n    - include_role:\n        name: \"ps\"\n      vars:\n        script_path: \"../ad/{{domain_name}}/scripts\"\n        ps_script: \"{{script_path}}/{{item}}\"\n      loop: \"{{lab.hosts[dict_key].scripts | default([]) }}\"\n\n- name: \"Setup vulnerabilities with tasks\"\n  hosts: linux_domain\n  become: true\n  tasks:\n    - include_role:\n        name: \"ps\"\n      vars:\n        script_path: \"../ad/{{domain_name}}/scripts\"\n        ps_script: \"{{script_path}}/{{item}}\"\n      loop: \"{{lab.hosts[dict_key].scripts | default([]) }}\""
  },
  {
    "path": "ansible/wait5m.yml",
    "content": "- name: \"wait\"\n  hosts: localhost\n  connection: local\n  tasks:\n    - name: Wait 5 minutes to finish\n      ansible.builtin.pause:\n        minutes: 5"
  },
  {
    "path": "docs/img/azure_architecture.excalidraw",
    "content": "{\n  \"type\": \"excalidraw\",\n  \"version\": 2,\n  \"source\": \"https://excalidraw.com\",\n  \"elements\": [\n    {\n      \"type\": \"ellipse\",\n      \"version\": 1190,\n      \"versionNonce\": 879623545,\n      \"isDeleted\": false,\n      \"id\": \"uplFgC4-Dk3AkhEnhzuf-\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 536.2073479545918,\n      \"y\": 327.76945353274573,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 96.53424794765822,\n      \"height\": 92.54522943742442,\n      \"seed\": 142161433,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"cMIoGo9YKI2HKyZ8oisu_\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 877,\n      \"versionNonce\": 261452439,\n      \"isDeleted\": false,\n      \"id\": \"vFgxYfpNuQWo0OgJWKPKQ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 585.7083172551709,\n      \"y\": 330.0929691802562,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 1.5956074040935242,\n      \"height\": 90.15181833128413,\n      \"seed\": 1610418937,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -1.5956074040935242,\n          90.15181833128413\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 892,\n      \"versionNonce\": 1956767321,\n      \"isDeleted\": false,\n      \"id\": \"uovg_10TscLf96o6_yAGA\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 554.3334108187364,\n      \"y\": 342.93186601277887,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 71.00452948216183,\n      \"height\": 16.753877742982,\n      \"seed\": 1173570521,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -1.595607404093524,\n          -0.797803702046762\n        ],\n        [\n          -1.595607404093524,\n          -1.5956074040935238\n        ],\n        [\n          1.5956074040935238,\n          2.393411106140286\n        ],\n        [\n          11.96705553070143,\n          9.57364442456114\n        ],\n        [\n          42.283596208478386,\n          15.158270338888476\n        ],\n        [\n          45.47481101666544,\n          13.56266293479494\n        ],\n        [\n          58.23967024941363,\n          10.371448126607909\n        ],\n        [\n          68.61111837602157,\n          2.393411106140286\n        ],\n        [\n          68.61111837602157,\n          0.797803702046762\n        ],\n        [\n          69.4089220780683,\n          0.797803702046762\n        ],\n        [\n          68.61111837602157,\n          3.1912148081870484\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 882,\n      \"versionNonce\": 194578359,\n      \"isDeleted\": false,\n      \"id\": \"5mX_8OE34_d8eN6Nr7ucJ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 551.3379040475968,\n      \"y\": 410.70659403230053,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 70.2067257801151,\n      \"height\": 18.349485147075526,\n      \"seed\": 107962553,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          13.562662934794957,\n          -9.573644424561149\n        ],\n        [\n          47.07041842075897,\n          -18.349485147075526\n        ],\n        [\n          57.4418665473669,\n          -16.753877742982002\n        ],\n        [\n          67.015510971928,\n          -7.978037020467623\n        ],\n        [\n          68.61111837602155,\n          -4.786822212280571\n        ],\n        [\n          70.2067257801151,\n          -3.989018510233811\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 875,\n      \"versionNonce\": 1545974585,\n      \"isDeleted\": false,\n      \"id\": \"Kva-tLNzKOz51EnpQZnhE\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 536.1346926202987,\n      \"y\": 376.21983373856875,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 94.14083684151794,\n      \"height\": 0.7978037020467621,\n      \"seed\": 521462169,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          94.14083684151794,\n          0.7978037020467621\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 887,\n      \"versionNonce\": 682424535,\n      \"isDeleted\": false,\n      \"id\": \"I0cDOu8M0fGL2OpsNIocx\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 584.8397496811956,\n      \"y\": 332.338595830696,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 23.934111061402866,\n      \"height\": 90.94962203333087,\n      \"seed\": 219629177,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          2.3934111061402867,\n          -0.7978037020467623\n        ],\n        [\n          6.382429616374097,\n          0\n        ],\n        [\n          16.753877742982,\n          7.978037020467621\n        ],\n        [\n          18.349485147075526,\n          10.371448126607909\n        ],\n        [\n          23.934111061402866,\n          38.29457769824459\n        ],\n        [\n          23.934111061402866,\n          51.05943693099279\n        ],\n        [\n          19.147288849122294,\n          67.01551097192802\n        ],\n        [\n          11.169251828654675,\n          82.17378131081651\n        ],\n        [\n          3.9890185102338105,\n          90.1518183312841\n        ],\n        [\n          1.5956074040935242,\n          89.35401462923738\n        ],\n        [\n          1.5956074040935242,\n          90.1518183312841\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 883,\n      \"versionNonce\": 1063052313,\n      \"isDeleted\": false,\n      \"id\": \"6gWtAFcMSqKWTk-KP3rz5\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 583.9009247044912,\n      \"y\": 334.0533564519932,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 27.92312957163668,\n      \"height\": 83.76938871491002,\n      \"seed\": 1530531673,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -0.7978037020467624,\n          -1.5956074040935246\n        ],\n        [\n          -14.360466636841723,\n          8.775840722514387\n        ],\n        [\n          -23.934111061402863,\n          24.731914763449627\n        ],\n        [\n          -27.92312957163668,\n          47.868222122805726\n        ],\n        [\n          -24.73191476344963,\n          63.02649246169427\n        ],\n        [\n          -20.742896253215818,\n          70.20672578011508\n        ],\n        [\n          -17.551681445028773,\n          71.00452948216189\n        ],\n        [\n          -11.169251828654671,\n          75.79135169444241\n        ],\n        [\n          -7.18023331842086,\n          82.1737813108165\n        ],\n        [\n          -3.989018510233811,\n          82.1737813108165\n        ]\n      ]\n    },\n    {\n      \"id\": \"CXbgcj4C2cvKYtAEM9oj9\",\n      \"type\": \"text\",\n      \"x\": 641.8406731058137,\n      \"y\": 359.74953599139485,\n      \"width\": 82.65992736816406,\n      \"height\": 25,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"transparent\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 991192249,\n      \"version\": 406,\n      \"versionNonce\": 476431863,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"Internet\",\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 18,\n      \"containerId\": null,\n      \"originalText\": \"Internet\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"id\": \"tgYncXat4V-ZZ6dAX7H1M\",\n      \"type\": \"rectangle\",\n      \"x\": 825,\n      \"y\": 65.66666666666674,\n      \"width\": 1039,\n      \"height\": 672.3333333333334,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"transparent\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"seed\": 1949355385,\n      \"version\": 86,\n      \"versionNonce\": 440072441,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"id\": \"AwhPnr7jU-dMecvIaN0uh\",\n      \"type\": \"text\",\n      \"x\": 912.3333333333333,\n      \"y\": 101.33333333333326,\n      \"width\": 117.41987609863281,\n      \"height\": 25,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"transparent\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"u2P_98sWb5Bhs5WpsKqzX\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 306581529,\n      \"version\": 42,\n      \"versionNonce\": 1297555191,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"Azure Cloud\",\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 18,\n      \"containerId\": null,\n      \"originalText\": \"Azure Cloud\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1065,\n      \"versionNonce\": 778547193,\n      \"isDeleted\": false,\n      \"id\": \"822jLVnQzcpmF5a9dXVNI\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 871.0299142994818,\n      \"y\": 100.02679836146,\n      \"strokeColor\": \"#364fc7\",\n      \"backgroundColor\": \"#364fc7\",\n      \"width\": 34.602985560653366,\n      \"height\": 46.08332597580886,\n      \"seed\": 1808334999,\n      \"groupIds\": [\n        \"UZy6hKatbQTMO105II0jD\",\n        \"u2P_98sWb5Bhs5WpsKqzX\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -23.802008451178224,\n          38.612875109738454\n        ],\n        [\n          -9.241920562053707,\n          39.14703774162111\n        ],\n        [\n          10.800977109475136,\n          -6.936288234187749\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1138,\n      \"versionNonce\": 287713303,\n      \"isDeleted\": false,\n      \"id\": \"oy7qYkLiG_n1PGGebhpF4\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 884.7935521793275,\n      \"y\": 89.01839762974379,\n      \"strokeColor\": \"#364fc7\",\n      \"backgroundColor\": \"#364fc7\",\n      \"width\": 43.93680928103998,\n      \"height\": 44.77892013157281,\n      \"seed\": 1982518711,\n      \"groupIds\": [\n        \"UZy6hKatbQTMO105II0jD\",\n        \"u2P_98sWb5Bhs5WpsKqzX\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -4.998495928910919,\n          11.442322194536532\n        ],\n        [\n          14.172843983209026,\n          38.21963697033442\n        ],\n        [\n          -19.154235186843934,\n          44.608403453747805\n        ],\n        [\n          24.782574094196043,\n          44.77892013157281\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"id\": \"x22xWojHWMJuGKn0WqHFW\",\n      \"type\": \"rectangle\",\n      \"x\": 987.9724005808569,\n      \"y\": 160.0773848420983,\n      \"width\": 827.1403326680916,\n      \"height\": 504.28580527481137,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"sh8LougDhYvcHPpOZxfhb\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"seed\": 53679575,\n      \"version\": 1172,\n      \"versionNonce\": 1387588311,\n      \"isDeleted\": false,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"id\": \"XFdEwGB-Wu5mcUaa43gOM\",\n      \"type\": \"text\",\n      \"x\": 1627.4479489807643,\n      \"y\": 186.34455600640382,\n      \"width\": 161.89770889431975,\n      \"height\": 25.655717514518976,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"sh8LougDhYvcHPpOZxfhb\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 343127385,\n      \"version\": 835,\n      \"versionNonce\": 260379161,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"192.168.56.0/24\",\n      \"fontSize\": 20.52457401161518,\n      \"fontFamily\": 1,\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 17,\n      \"containerId\": null,\n      \"originalText\": \"192.168.56.0/24\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1920,\n      \"versionNonce\": 1688172535,\n      \"isDeleted\": false,\n      \"id\": \"XtLMpQckYEMcpPvaOAINJ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 4,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1036.9878536966476,\n      \"y\": 175.77801756229388,\n      \"strokeColor\": \"#1864ab\",\n      \"backgroundColor\": \"#66cce6\",\n      \"width\": 25.28470724739857,\n      \"height\": 44.26282148404956,\n      \"seed\": 1593209689,\n      \"groupIds\": [\n        \"sWM2do492m2OlX37eT7Fl\",\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -25.28470724739857,\n          22.735422651414982\n        ],\n        [\n          -2.00838706310297,\n          44.26282148404956\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 2152,\n      \"versionNonce\": 1361929977,\n      \"isDeleted\": false,\n      \"id\": \"0CU9IwircF79r5_kKcKUq\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 4,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1047.9404335765153,\n      \"y\": 175.03260388578474,\n      \"strokeColor\": \"#1864ab\",\n      \"backgroundColor\": \"#66cce6\",\n      \"width\": 25.304369328744436,\n      \"height\": 44.26282148404956,\n      \"seed\": 106995769,\n      \"groupIds\": [\n        \"sWM2do492m2OlX37eT7Fl\",\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          25.304369328744436,\n          22.735422651414982\n        ],\n        [\n          2.0099488399280823,\n          44.26282148404956\n        ]\n      ]\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 1860,\n      \"versionNonce\": 805003543,\n      \"isDeleted\": false,\n      \"id\": \"hvtWFYMQTyYr7TOxQNLpS\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1025.7692007895155,\n      \"y\": 193.34882305035586,\n      \"strokeColor\": \"#495057\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 7.151150347507662,\n      \"height\": 7.151150347507662,\n      \"seed\": 498217241,\n      \"groupIds\": [\n        \"sWM2do492m2OlX37eT7Fl\",\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 1905,\n      \"versionNonce\": 1756897241,\n      \"isDeleted\": false,\n      \"id\": \"74qdPU0xdiRFxKrBuff83\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1038.231635574137,\n      \"y\": 193.5160784862519,\n      \"strokeColor\": \"#495057\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 7.151150347507662,\n      \"height\": 7.151150347507662,\n      \"seed\": 2053023225,\n      \"groupIds\": [\n        \"sWM2do492m2OlX37eT7Fl\",\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 1954,\n      \"versionNonce\": 909977143,\n      \"isDeleted\": false,\n      \"id\": \"BQRIATj4gqDlvCm1EROCF\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1051.7149239657892,\n      \"y\": 193.4146964401125,\n      \"strokeColor\": \"#495057\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 7.151150347507662,\n      \"height\": 7.151150347507662,\n      \"seed\": 2003402457,\n      \"groupIds\": [\n        \"sWM2do492m2OlX37eT7Fl\",\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 1857,\n      \"versionNonce\": 876133561,\n      \"isDeleted\": false,\n      \"id\": \"Wl7AXyTyNMk3b3OYg8qLL\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1005.166460451312,\n      \"y\": 225.39776470481524,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#364fc7\",\n      \"width\": 76.49380878402103,\n      \"height\": 49.03449281026989,\n      \"seed\": 1130773433,\n      \"groupIds\": [\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 19.61379712410795,\n      \"fontFamily\": 1,\n      \"text\": \"Virtual\\nNetwork\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Virtual\\nNetwork\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 42.000000000000014\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1058,\n      \"versionNonce\": 1447642967,\n      \"isDeleted\": false,\n      \"id\": \"6UMPol5zLg6IVit-YoCbF\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1197.5392994862877,\n      \"y\": 314.16472642668555,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#868e96\",\n      \"width\": 41.63900243351605,\n      \"height\": 11.96910596267062,\n      \"seed\": 169682423,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          19.218001123161184,\n          -6.068842459945697\n        ],\n        [\n          12.306263877112068,\n          -11.29479013378779\n        ],\n        [\n          31.35568604305254,\n          -11.126211176567086\n        ],\n        [\n          23.263896096458378,\n          -5.900263502724988\n        ],\n        [\n          41.63900243351605,\n          -1.5172106149864244\n        ],\n        [\n          2.69726331553143,\n          0.6743158288828293\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1075,\n      \"versionNonce\": 55754137,\n      \"isDeleted\": false,\n      \"id\": \"4gKuiSVzgU5zXQPVrsm4M\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1182.4729818454052,\n      \"y\": 240.6242747832859,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 71.98321473324478,\n      \"height\": 62.728229981827305,\n      \"seed\": 1972588311,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 897,\n      \"versionNonce\": 510936183,\n      \"isDeleted\": false,\n      \"id\": \"B_3Giz805Ui3Ky1mz4ldg\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1191.8948462501974,\n      \"y\": 252.20108565529597,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#59b6da\",\n      \"width\": 55.44048836597695,\n      \"height\": 40.9097152055396,\n      \"seed\": 514282551,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 872,\n      \"versionNonce\": 1698275961,\n      \"isDeleted\": false,\n      \"id\": \"Y8Shrj73uK17JWh6rvtiI\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1219.6371694807258,\n      \"y\": 245.35382103781382,\n      \"strokeColor\": \"#82c91e\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 3.173863083476339,\n      \"height\": 2.2851814201029743,\n      \"seed\": 1295889751,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 900,\n      \"versionNonce\": 1585618327,\n      \"isDeleted\": false,\n      \"id\": \"nWKxNY86ASSntM1gnPWHj\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1197.416229269838,\n      \"y\": 312.7175736866611,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 41.80758139073692,\n      \"height\": 8.091789946594178,\n      \"seed\": 1487598199,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1416,\n      \"versionNonce\": 917564249,\n      \"isDeleted\": false,\n      \"id\": \"TVL2vn8Yijth6vtyAmIrl\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1219.9387114579283,\n      \"y\": 273.08749064030775,\n      \"strokeColor\": \"#99d2ea\",\n      \"backgroundColor\": \"#99d2ea\",\n      \"width\": 9.62325599292749,\n      \"height\": 19.129117180901776,\n      \"seed\": 968067991,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          9.095150481120506,\n          -7.1891846987564945\n        ],\n        [\n          9.62325599292749,\n          5.549546083250626\n        ],\n        [\n          0.6454622922085516,\n          11.939932482145283\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1210,\n      \"versionNonce\": 2041107127,\n      \"isDeleted\": false,\n      \"id\": \"beawX6OIKL_toHg4NfHP9\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1219.0172252136695,\n      \"y\": 269.57969229048695,\n      \"strokeColor\": \"#000\",\n      \"backgroundColor\": \"#000000\",\n      \"width\": 17.000696729698905,\n      \"height\": 13.945897371768192,\n      \"seed\": 1552679095,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          7.610420196688328,\n          -7.544268539716403\n        ],\n        [\n          2.6455684080248534,\n          -13.945897371768192\n        ],\n        [\n          -9.390276533010576,\n          -5.337441687962625\n        ],\n        [\n          -0.1841230692746738,\n          -0.9237879844550655\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1209,\n      \"versionNonce\": 1879840825,\n      \"isDeleted\": false,\n      \"id\": \"cNDO0djNdSRovGgKplKQs\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1207.8236917386369,\n      \"y\": 265.88993440521824,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 8.923969558630365,\n      \"height\": 18.152647395677405,\n      \"seed\": 853070295,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.48054249981645,\n          6.2000239344391055\n        ],\n        [\n          8.923969558630365,\n          18.152647395677405\n        ],\n        [\n          1.7182798529039773,\n          12.847472276518157\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 724,\n      \"versionNonce\": 2022400983,\n      \"isDeleted\": false,\n      \"id\": \"FLuHTL7vlxV7h0XCrkNXu\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1154.0423222095924,\n      \"y\": 330.3863532045007,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 124.7317331446735,\n      \"height\": 49.44168574184478,\n      \"seed\": 95321847,\n      \"groupIds\": [\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"SAhg2CJFAfFnLulnaYOt8\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 19.776674296737912,\n      \"fontFamily\": 1,\n      \"text\": \"DC01\\n192.168.56.10\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"DC01\\n192.168.56.10\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 42\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1105,\n      \"versionNonce\": 858695961,\n      \"isDeleted\": false,\n      \"id\": \"2my-5pBCON_yAwxnie5DJ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1395.6512835042092,\n      \"y\": 315.35275336429584,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#868e96\",\n      \"width\": 42.11414526485284,\n      \"height\": 12.105685480990102,\n      \"seed\": 222624087,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          19.437297814547392,\n          -6.138094046699237\n        ],\n        [\n          12.446690705806747,\n          -11.423675031356881\n        ],\n        [\n          31.71348590794583,\n          -11.253172418948576\n        ],\n        [\n          23.52936051234695,\n          -5.96759143429093\n        ],\n        [\n          42.11414526485284,\n          -1.5345235116748095\n        ],\n        [\n          2.7280417985330034,\n          0.6820104496332223\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1122,\n      \"versionNonce\": 1530843383,\n      \"isDeleted\": false,\n      \"id\": \"DFR-zvglw6IOPw2Q6hmG3\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1380.4130440495621,\n      \"y\": 240.9731313188813,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 72.80461549834928,\n      \"height\": 63.444022077132644,\n      \"seed\": 522827383,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 944,\n      \"versionNonce\": 428613113,\n      \"isDeleted\": false,\n      \"id\": \"UVJ8QjuF3HWobQSAG-Ozx\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1389.9424213885782,\n      \"y\": 252.68204522828682,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#59b6da\",\n      \"width\": 56.07312001115059,\n      \"height\": 41.37653613726047,\n      \"seed\": 1270468503,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 919,\n      \"versionNonce\": 726112791,\n      \"isDeleted\": false,\n      \"id\": \"odwKmZ8kANyEnuV6zzU_1\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1418.0013123857973,\n      \"y\": 245.75664644554797,\n      \"strokeColor\": \"#82c91e\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 3.210080048428036,\n      \"height\": 2.3112576348681957,\n      \"seed\": 1563018423,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 947,\n      \"versionNonce\": 1109915353,\n      \"isDeleted\": false,\n      \"id\": \"KWhh-fEJ8T0pQvlnTDDio\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1395.5268089330036,\n      \"y\": 313.8890871582879,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 42.28464787726131,\n      \"height\": 8.184125395598898,\n      \"seed\": 1662916055,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1463,\n      \"versionNonce\": 1301954359,\n      \"isDeleted\": false,\n      \"id\": \"WB4lpuWkVZLwFHecsEX-S\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1418.3062952597659,\n      \"y\": 273.80678506814695,\n      \"strokeColor\": \"#99d2ea\",\n      \"backgroundColor\": \"#99d2ea\",\n      \"width\": 9.73306700740746,\n      \"height\": 19.347399617250225,\n      \"seed\": 78332663,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          9.198935281391208,\n          -7.2712205154940435\n        ],\n        [\n          9.73306700740746,\n          5.612871976872594\n        ],\n        [\n          0.6528276651309886,\n          12.076179101756182\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1253,\n      \"versionNonce\": 529904569,\n      \"isDeleted\": false,\n      \"id\": \"StkSV3WaCj9GwIERrtudM\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1417.3742939321105,\n      \"y\": 270.2589592166503,\n      \"strokeColor\": \"#000\",\n      \"backgroundColor\": \"#000000\",\n      \"width\": 17.19469175135546,\n      \"height\": 10.277622663204461,\n      \"seed\": 307612695,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          7.697262733458771,\n          -7.630356219651804\n        ],\n        [\n          0.12414939892676406,\n          -10.277622663204461\n        ],\n        [\n          -9.497429017896687,\n          -5.398347257440731\n        ],\n        [\n          -0.18622409839008727,\n          -0.9343293330185839\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1229,\n      \"versionNonce\": 345718871,\n      \"isDeleted\": false,\n      \"id\": \"sLXF7F-uP5QkLH76ptug0\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1406.053030999666,\n      \"y\": 266.5270974886836,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 9.02580101267687,\n      \"height\": 18.359787331212893,\n      \"seed\": 1477587255,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.5773140058358,\n          6.270772433548056\n        ],\n        [\n          9.02580101267687,\n          18.359787331212893\n        ],\n        [\n          1.7378871515092051,\n          12.994074836527426\n        ],\n        [\n          0.9530348895373422,\n          2.2626498471565153\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 774,\n      \"versionNonce\": 100193433,\n      \"isDeleted\": false,\n      \"id\": \"rWHSJYGi-z3aEn2JRzgPA\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1354.585534638246,\n      \"y\": 331.75948519328057,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 117.81405377513887,\n      \"height\": 50.00586502512499,\n      \"seed\": 793047639,\n      \"groupIds\": [\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"l8S7i1jyyXiaBDgV1tqr5\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20.002346010049994,\n      \"fontFamily\": 1,\n      \"text\": \"DC02\\n192.168.56.11\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"DC02\\n192.168.56.11\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 43.00000000000001\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1146,\n      \"versionNonce\": 304029047,\n      \"isDeleted\": false,\n      \"id\": \"diGpIyZjjBogumvka-3ei\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1602.9069886300722,\n      \"y\": 312.904310821427,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#868e96\",\n      \"width\": 39.502252566143426,\n      \"height\": 11.354898510915737,\n      \"seed\": 1092554393,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          18.231808876681516,\n          -5.75741332947843\n        ],\n        [\n          11.67475480699789,\n          -10.71518591875149\n        ],\n        [\n          29.74663553563834,\n          -10.555257770710432\n        ],\n        [\n          22.070084429667197,\n          -5.597485181437367\n        ],\n        [\n          39.502252566143426,\n          -1.4393533323696077\n        ],\n        [\n          2.5588503686570885,\n          0.6397125921642455\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1163,\n      \"versionNonce\": 2030360953,\n      \"isDeleted\": false,\n      \"id\": \"QPYi7kXiMbyDrW4ST8ogZ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1588.6138151650698,\n      \"y\": 243.13766597242528,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 68.28931921353582,\n      \"height\": 59.50926388608093,\n      \"seed\": 659805049,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 985,\n      \"versionNonce\": 694834839,\n      \"isDeleted\": false,\n      \"id\": \"K_SB_hJvujifkLvTqp2RJ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1597.5521865383114,\n      \"y\": 254.12040043410678,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#59b6da\",\n      \"width\": 52.595500512288076,\n      \"height\": 38.8103894909224,\n      \"seed\": 2019359833,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 960,\n      \"versionNonce\": 972898905,\n      \"isDeleted\": false,\n      \"id\": \"ZJEhMOKlQOxtMALnKl9ZT\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1623.870882832097,\n      \"y\": 247.62451051121863,\n      \"strokeColor\": \"#82c91e\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 3.010992910649668,\n      \"height\": 2.1679148956677707,\n      \"seed\": 604899641,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 988,\n      \"versionNonce\": 1630628791,\n      \"isDeleted\": false,\n      \"id\": \"Rlq3Nm03rE9HpPxkIJPSG\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1602.7902338931801,\n      \"y\": 311.53142026936575,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 39.66218071418464,\n      \"height\": 7.67655110597116,\n      \"seed\": 1405778457,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1504,\n      \"versionNonce\": 364220217,\n      \"isDeleted\": false,\n      \"id\": \"gOhWw8t-9pepRu-AGBNdZ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1624.1569508607863,\n      \"y\": 273.9349972471319,\n      \"strokeColor\": \"#99d2ea\",\n      \"backgroundColor\": \"#99d2ea\",\n      \"width\": 9.129428337007726,\n      \"height\": 18.14748610881954,\n      \"seed\": 948293369,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.628423123391459,\n          -6.820264010127786\n        ],\n        [\n          9.129428337007726,\n          5.264765200800395\n        ],\n        [\n          0.6123397055310065,\n          11.327222098691754\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1325,\n      \"versionNonce\": 1972952279,\n      \"isDeleted\": false,\n      \"id\": \"h3JNkkwWuhhqlxKLXOnBH\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1623.2827516670122,\n      \"y\": 270.60720531486936,\n      \"strokeColor\": \"#000\",\n      \"backgroundColor\": \"#000000\",\n      \"width\": 16.128287825560832,\n      \"height\": 9.640210994861349,\n      \"seed\": 415467481,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          7.219883358734822,\n          -7.157126344669795\n        ],\n        [\n          0.11644973159250623,\n          -9.640210994861349\n        ],\n        [\n          -8.90840446682601,\n          -5.063545169018085\n        ],\n        [\n          -0.17467459738870414,\n          -0.8763828177146646\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1270,\n      \"versionNonce\": 1922121753,\n      \"isDeleted\": false,\n      \"id\": \"E2NC8whZC2YJ_Dclf9IiY\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1612.6636263134612,\n      \"y\": 267.1067912949962,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 8.466026532706854,\n      \"height\": 17.221124913189815,\n      \"seed\": 513221817,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.045354406858081,\n          5.881863086547217\n        ],\n        [\n          8.466026532706854,\n          17.221124913189815\n        ],\n        [\n          1.6301044876640471,\n          12.188190519546305\n        ],\n        [\n          0.8939282674287049,\n          2.122321732259305\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 822,\n      \"versionNonce\": 708127223,\n      \"isDeleted\": false,\n      \"id\": \"yN10xzW1r35OxRKCg_xMP\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1560.251122979581,\n      \"y\": 328.2935075014892,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 118.78127774814433,\n      \"height\": 46.90453284966765,\n      \"seed\": 1705256345,\n      \"groupIds\": [\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"5EnmiI-P42lyF3ONrbFTZ\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 18.76181313986706,\n      \"fontFamily\": 1,\n      \"text\": \"DC03\\n192.168.56.12\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"DC03\\n192.168.56.12\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 39.00000000000001\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1164,\n      \"versionNonce\": 511956217,\n      \"isDeleted\": false,\n      \"id\": \"l98Ot9PekroOdjP9lEmQy\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1277.667903583145,\n      \"y\": 558.8891049254931,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#868e96\",\n      \"width\": 40.19126481904397,\n      \"height\": 11.552954664583504,\n      \"seed\": 1303449591,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          18.54981453186638,\n          -5.8578361679578625\n        ],\n        [\n          11.87839000724785,\n          -10.90208397925488\n        ],\n        [\n          30.26548686778207,\n          -10.739366307922724\n        ],\n        [\n          22.455038643838353,\n          -5.695118496625704\n        ],\n        [\n          40.19126481904397,\n          -1.4644590419894659\n        ],\n        [\n          2.603482741314614,\n          0.6508706853286264\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1181,\n      \"versionNonce\": 1544213271,\n      \"isDeleted\": false,\n      \"id\": \"SjkWCQz52AOiHzEzGMPFg\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1263.125423534076,\n      \"y\": 487.90556559524134,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 69.48044565883353,\n      \"height\": 60.5472455026975,\n      \"seed\": 857340183,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1003,\n      \"versionNonce\": 1561382361,\n      \"isDeleted\": false,\n      \"id\": \"ICjA2HRkDMJ0ZoQFIDIO8\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1272.219701140432,\n      \"y\": 499.0798647936875,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#59b6da\",\n      \"width\": 53.51288982419438,\n      \"height\": 39.48733402349843,\n      \"seed\": 164150839,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 979,\n      \"versionNonce\": 1401837623,\n      \"isDeleted\": false,\n      \"id\": \"5D9sQqWIBXUO5ZOBf3kUj\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1298.997457438364,\n      \"y\": 492.4706712625337,\n      \"strokeColor\": \"#82c91e\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 3.063511713352388,\n      \"height\": 2.205728433613729,\n      \"seed\": 1688330071,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"cKxlt68orMI7e-h7oVKRx\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1006,\n      \"versionNonce\": 894151353,\n      \"isDeleted\": false,\n      \"id\": \"9WDqIBF_ZW6siHXKYHljB\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1277.549112368861,\n      \"y\": 557.4922679311202,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 40.35398249037628,\n      \"height\": 7.810448223943735,\n      \"seed\": 100260983,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1522,\n      \"versionNonce\": 1453603159,\n      \"isDeleted\": false,\n      \"id\": \"SzdGju6Z3AcdsR2Op3lhj\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1299.2885151667322,\n      \"y\": 519.240074808582,\n      \"strokeColor\": \"#99d2ea\",\n      \"backgroundColor\": \"#99d2ea\",\n      \"width\": 9.288667053221268,\n      \"height\": 18.46402097648012,\n      \"seed\": 1905603991,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.778923129568891,\n          -6.939225465885939\n        ],\n        [\n          9.288667053221268,\n          5.356595096473355\n        ],\n        [\n          0.6230203511306952,\n          11.524795510594183\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1312,\n      \"versionNonce\": 2144856985,\n      \"isDeleted\": false,\n      \"id\": \"AM8Ols6uc6B8KqXenn16Q\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1298.3990678815992,\n      \"y\": 515.8542383530967,\n      \"strokeColor\": \"#000\",\n      \"backgroundColor\": \"#000000\",\n      \"width\": 16.409603122998895,\n      \"height\": 9.808358962749613,\n      \"seed\": 1051224759,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          7.345815116432727,\n          -7.281963472344416\n        ],\n        [\n          0.11848088897473066,\n          -9.808358962749613\n        ],\n        [\n          -9.063788006566167,\n          -5.151865313767477\n        ],\n        [\n          -0.17772133346203983,\n          -0.8916689966135978\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1288,\n      \"versionNonce\": 2057369207,\n      \"isDeleted\": false,\n      \"id\": \"Yssq30taAhZtbKiO9FAzG\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1287.5947199898799,\n      \"y\": 512.2927688745284,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 8.613693960144035,\n      \"height\": 17.521501861417025,\n      \"seed\": 702020567,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.185684322372918,\n          5.984456621681159\n        ],\n        [\n          8.613693960144035,\n          17.521501861417025\n        ],\n        [\n          1.6585373463631312,\n          12.400781246988803\n        ],\n        [\n          0.9095204802636871,\n          2.159340018132377\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 842,\n      \"versionNonce\": 887689337,\n      \"isDeleted\": false,\n      \"id\": \"Wppg3DylzBOIIfB6_s9ew\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1230.0588718274837,\n      \"y\": 573.3605515685075,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 129.27139761875833,\n      \"height\": 47.72265829190373,\n      \"seed\": 1731750135,\n      \"groupIds\": [\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 19.08906331676149,\n      \"fontFamily\": 1,\n      \"text\": \"SRV02\\n192.168.56.22\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"SRV02\\n192.168.56.22\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 40\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1193,\n      \"versionNonce\": 910757783,\n      \"isDeleted\": false,\n      \"id\": \"OsXZ_-AjlU35m9gOlPvtS\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1530.7475568678317,\n      \"y\": 558.3734779006675,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#868e96\",\n      \"width\": 40.87643519766429,\n      \"height\": 11.749906473822545,\n      \"seed\": 1798068823,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          18.866047014306528,\n          -5.9576990571494886\n        ],\n        [\n          12.080889754775313,\n          -11.08793991191707\n        ],\n        [\n          30.78144512860547,\n          -10.922448271440706\n        ],\n        [\n          22.837846385739585,\n          -5.792207416673119\n        ],\n        [\n          40.87643519766429,\n          -1.4894247642873724\n        ],\n        [\n          2.647866247622004,\n          0.6619665619054733\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1212,\n      \"versionNonce\": 2051184985,\n      \"isDeleted\": false,\n      \"id\": \"huZRYMhZMFhX190PTk_sL\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1515.9571603472068,\n      \"y\": 486.17982939028104,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 70.66493048341198,\n      \"height\": 61.57943942125872,\n      \"seed\": 1803351927,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1032,\n      \"versionNonce\": 1899497017,\n      \"isDeleted\": false,\n      \"id\": \"h6khX5G-YpPxeMoDqpr_Q\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1525.2064748666555,\n      \"y\": 497.5446251766574,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#59b6da\",\n      \"width\": 54.42516385057778,\n      \"height\": 40.16050397038617,\n      \"seed\": 234680471,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 1008,\n      \"versionNonce\": 1658672599,\n      \"isDeleted\": false,\n      \"id\": \"TqllulP3IVZg-yrzbF9fj\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1552.4407314888208,\n      \"y\": 490.82275980861306,\n      \"strokeColor\": \"#82c91e\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 3.115737675635388,\n      \"height\": 2.243331126457489,\n      \"seed\": 207668663,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"6AoiEoK2dW91-YLQdsgSp\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1035,\n      \"versionNonce\": 1152177945,\n      \"isDeleted\": false,\n      \"id\": \"auZXiaL4Bn_q_sPMP8V4q\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1530.6267405313813,\n      \"y\": 556.9528279873275,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 41.04192683814082,\n      \"height\": 7.943598742865901,\n      \"seed\": 1976366807,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1551,\n      \"versionNonce\": 1250067191,\n      \"isDeleted\": false,\n      \"id\": \"24wODDL8JiW0R1dYrpW8a\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1552.736751094722,\n      \"y\": 518.0485212833225,\n      \"strokeColor\": \"#99d2ea\",\n      \"backgroundColor\": \"#99d2ea\",\n      \"width\": 9.44701786776737,\n      \"height\": 18.778790872383322,\n      \"seed\": 14025719,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.928583960389902,\n          -7.05752360258802\n        ],\n        [\n          9.44701786776737,\n          5.447912956383734\n        ],\n        [\n          0.6336414423502509,\n          11.721267269795302\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1341,\n      \"versionNonce\": 1997835257,\n      \"isDeleted\": false,\n      \"id\": \"gf5Ue0Z4fDYUaxK-EC8Cg\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1551.8321407403043,\n      \"y\": 514.6049639559858,\n      \"strokeColor\": \"#000\",\n      \"backgroundColor\": \"#000000\",\n      \"width\": 16.68934983003626,\n      \"height\": 9.97556935173361,\n      \"seed\": 494955799,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          7.471044689258119,\n          -7.406104518711323\n        ],\n        [\n          0.12050072079449521,\n          -9.97556935173361\n        ],\n        [\n          -9.218305140778142,\n          -5.239692992829778\n        ],\n        [\n          -0.1807510811916857,\n          -0.9068699410666883\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1323,\n      \"versionNonce\": 457509911,\n      \"isDeleted\": false,\n      \"id\": \"-iPzSV0ZAbnmq0FMK248I\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1540.8436030956855,\n      \"y\": 510.9827794588173,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 8.760538006445234,\n      \"height\": 17.820203933084482,\n      \"seed\": 1195422263,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.325231770100144,\n          6.086478103905606\n        ],\n        [\n          8.760538006445234,\n          17.820203933084482\n        ],\n        [\n          1.6868116658372752,\n          12.612186586443586\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 872,\n      \"versionNonce\": 1886561497,\n      \"isDeleted\": false,\n      \"id\": \"3iPzEpimivWqJgo-LP1IU\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1482.6278244536288,\n      \"y\": 574.3299387300013,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 130.87333144529953,\n      \"height\": 48.53622193559225,\n      \"seed\": 385569623,\n      \"groupIds\": [\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 19.414488774236894,\n      \"fontFamily\": 1,\n      \"text\": \"SRV03\\n192.168.56.23\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"SRV03\\n192.168.56.23\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 41.000000000000014\n    },\n    {\n      \"id\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n      \"type\": \"rectangle\",\n      \"x\": 893.5820175067391,\n      \"y\": 303.56993169125974,\n      \"width\": 169.3126193900116,\n      \"height\": 180.38370511676985,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"seed\": 279786679,\n      \"version\": 1136,\n      \"versionNonce\": 803620729,\n      \"isDeleted\": false,\n      \"boundElements\": [\n        {\n          \"id\": \"5EnmiI-P42lyF3ONrbFTZ\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"6AoiEoK2dW91-YLQdsgSp\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"l8S7i1jyyXiaBDgV1tqr5\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"cKxlt68orMI7e-h7oVKRx\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"SAhg2CJFAfFnLulnaYOt8\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 916,\n      \"versionNonce\": 1579075735,\n      \"isDeleted\": false,\n      \"id\": \"fAvSvt8t153-tb4euGzc3\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1043.35857112288,\n      \"y\": 369.27886540595165,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#DD4814\",\n      \"width\": 121.75687832837134,\n      \"height\": 121.75497745227408,\n      \"seed\": 2057201689,\n      \"groupIds\": [\n        \"FPK4mFxLxRtOyBf1N8gHR\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          -0.07921308421572881,\n          3.1326417621507425\n        ],\n        [\n          -0.3142987188836881,\n          6.224163727094603\n        ],\n        [\n          -0.7014446651967967,\n          9.270746380759999\n        ],\n        [\n          -1.2368168585536337,\n          12.268555658545207\n        ],\n        [\n          -1.916588509617518,\n          15.213779321643544\n        ],\n        [\n          -2.7369328290519013,\n          18.10258330545334\n        ],\n        [\n          -3.6940375780496986,\n          20.93114809590283\n        ],\n        [\n          -4.784068692009697,\n          23.695639628390563\n        ],\n        [\n          -6.003199381594779,\n          26.39223838884469\n        ],\n        [\n          -7.347610132733612,\n          29.017124863193548\n        ],\n        [\n          -8.813466880824448,\n          31.566457711570628\n        ],\n        [\n          -10.39695738706037,\n          34.036424695169046\n        ],\n        [\n          -12.094254862104936,\n          36.423191749387314\n        ],\n        [\n          -13.901525241356396,\n          38.72293936015357\n        ],\n        [\n          -15.814949010743147,\n          40.931840738131356\n        ],\n        [\n          -17.830699380928287,\n          43.046069093983704\n        ],\n        [\n          -19.944949562575545,\n          45.06180491363917\n        ],\n        [\n          -22.153887316877686,\n          46.97521413249607\n        ],\n        [\n          -24.45367130396847,\n          48.782469961217735\n        ],\n        [\n          -26.840489285041023,\n          50.47976016099736\n        ],\n        [\n          -29.310507195493784,\n          52.06325066723337\n        ],\n        [\n          -31.85989824598994,\n          53.52910741532415\n        ],\n        [\n          -34.48485019772275,\n          54.87352544172786\n        ],\n        [\n          -37.181528986090946,\n          56.092656131313035\n        ],\n        [\n          -39.94611509702236,\n          57.18269452053786\n        ],\n        [\n          -42.774774465915556,\n          58.139806544800535\n        ],\n        [\n          -45.6636875786988,\n          58.960158139499846\n        ],\n        [\n          -48.60903492130038,\n          59.639937065828605\n        ],\n        [\n          -51.6069824291188,\n          60.17531653445045\n        ],\n        [\n          -54.65371058808214,\n          60.562462480763536\n        ],\n        [\n          -57.74538533358883,\n          60.79755539069639\n        ],\n        [\n          -60.87819806446477,\n          60.87677575017707\n        ],\n        [\n          -64.0110944608868,\n          60.79755539069634\n        ],\n        [\n          -67.10285287193989,\n          60.5624624807636\n        ],\n        [\n          -70.1496501459197,\n          60.175316534450275\n        ],\n        [\n          -73.14765949348964,\n          59.63993706582848\n        ],\n        [\n          -76.09306140057795,\n          58.96015813949971\n        ],\n        [\n          -78.9820218025832,\n          58.139806544800614\n        ],\n        [\n          -81.81072846069821,\n          57.182694520537765\n        ],\n        [\n          -84.5753473103216,\n          56.092656131312964\n        ],\n        [\n          -87.27205519974918,\n          54.87352544172779\n        ],\n        [\n          -89.89703261490929,\n          53.52910741532406\n        ],\n        [\n          -92.44644731001647,\n          52.06325066723346\n        ],\n        [\n          -94.91648158981522,\n          50.47976016099739\n        ],\n        [\n          -97.30330866496891,\n          48.78246996121791\n        ],\n        [\n          -99.60310356495712,\n          46.9752141324962\n        ],\n        [\n          -101.81204131925912,\n          45.06180491363929\n        ],\n        [\n          -103.92629695735508,\n          43.04606909398376\n        ],\n        [\n          -105.94204732754048,\n          40.93184073813134\n        ],\n        [\n          -107.85546654988633,\n          38.722939360153546\n        ],\n        [\n          -109.66273147268927,\n          36.42319174938722\n        ],\n        [\n          -111.36001712542844,\n          34.03642469516903\n        ],\n        [\n          -112.94349762817498,\n          31.566457711570607\n        ],\n        [\n          -114.4093498292253,\n          29.01712486319365\n        ],\n        [\n          -115.75374830335467,\n          26.392238388844753\n        ],\n        [\n          -116.97286898945053,\n          23.695639628390474\n        ],\n        [\n          -118.06288691699284,\n          20.931148095902877\n        ],\n        [\n          -119.01997825222094,\n          18.102583305453365\n        ],\n        [\n          -119.8403175699107,\n          15.213779321643521\n        ],\n        [\n          -120.5200804679215,\n          12.268555658545303\n        ],\n        [\n          -121.05544271462705,\n          9.27074638075996\n        ],\n        [\n          -121.44257945318324,\n          6.224163727094528\n        ],\n        [\n          -121.6776661819827,\n          3.132641762150776\n        ],\n        [\n          -121.75687832837136,\n          7.105427357601002e-14\n        ],\n        [\n          -121.67766346796796,\n          -3.132809093243303\n        ],\n        [\n          -121.44256896657087,\n          -6.224491114014874\n        ],\n        [\n          -121.05541992258617,\n          -9.271219272978222\n        ],\n        [\n          -120.52004136337267,\n          -12.269166780796567\n        ],\n        [\n          -119.84025845838342,\n          -15.214510485765615\n        ],\n        [\n          -119.01989640549073,\n          -18.103423598549057\n        ],\n        [\n          -118.06278006153966,\n          -20.93208660507465\n        ],\n        [\n          -116.97273485175396,\n          -23.696669078373596\n        ],\n        [\n          -115.75358551930256,\n          -26.393347866741557\n        ],\n        [\n          -114.40915748940967,\n          -29.018296180842164\n        ],\n        [\n          -112.94327573259555,\n          -31.56769450660329\n        ],\n        [\n          -111.35976521938125,\n          -34.03771241705603\n        ],\n        [\n          -109.66245137499077,\n          -36.424526760496114\n        ],\n        [\n          -107.85515916994449,\n          -38.724312566403086\n        ],\n        [\n          -105.941712665355,\n          -40.93324668307277\n        ],\n        [\n          -103.92593865055873,\n          -43.04750050235237\n        ],\n        [\n          -101.8116630054844,\n          -45.06325269135381\n        ],\n        [\n          -99.60270706301999,\n          -46.97667646074068\n        ],\n        [\n          -97.30289943131824,\n          -48.783946839992055\n        ],\n        [\n          -94.9160632620835,\n          -50.48123976799617\n        ],\n        [\n          -92.44602534465247,\n          -52.06472936482385\n        ],\n        [\n          -89.89660701191272,\n          -53.53059156936324\n        ],\n        [\n          -87.27164050965001,\n          -54.87500095639003\n        ],\n        [\n          -84.57494353311984,\n          -56.094132555383304\n        ],\n        [\n          -81.81034650929097,\n          -57.18416207787886\n        ],\n        [\n          -78.98166895223548,\n          -58.14126387130044\n        ],\n        [\n          -76.09274128892245,\n          -58.961613192479355\n        ],\n        [\n          -73.14738667105601,\n          -59.641385298247464\n        ],\n        [\n          -70.14942825034034,\n          -60.176755047569976\n        ],\n        [\n          -67.10269645374451,\n          -60.563897697278705\n        ],\n        [\n          -64.01101079534054,\n          -60.7989882129104\n        ],\n        [\n          -60.878198064464726,\n          -60.87820170209703\n        ],\n        [\n          -57.745348957264454,\n          -60.79898821291046\n        ],\n        [\n          -54.65363056016823,\n          -60.56389769727871\n        ],\n        [\n          -51.606873300145224,\n          -60.17675504756999\n        ],\n        [\n          -48.6088966912674,\n          -59.641385298247364\n        ],\n        [\n          -45.66352752287113,\n          -58.96161319247935\n        ],\n        [\n          -42.77459258429314,\n          -58.141263871300445\n        ],\n        [\n          -39.945918664870064,\n          -57.18416207787901\n        ],\n        [\n          -37.181325278673846,\n          -56.09413255538324\n        ],\n        [\n          -34.48464649030576,\n          -54.87500095638998\n        ],\n        [\n          -31.859687263308018,\n          -53.53059156936342\n        ],\n        [\n          -29.31028893754677,\n          -52.06472936482392\n        ],\n        [\n          -26.84027830235899,\n          -50.48123976799603\n        ],\n        [\n          -24.453467596551356,\n          -48.783946839992154\n        ],\n        [\n          -22.15369088472539,\n          -46.976676460740535\n        ],\n        [\n          -19.944760405688037,\n          -45.06325269135387\n        ],\n        [\n          -17.830517499305813,\n          -43.04750050235246\n        ],\n        [\n          -15.814781679650485,\n          -40.933246683072824\n        ],\n        [\n          -13.901365185528688,\n          -38.724312566403086\n        ],\n        [\n          -12.09410935680699,\n          -36.42452676049609\n        ],\n        [\n          -10.396833707557128,\n          -34.03771241705598\n        ],\n        [\n          -8.813357751850935,\n          -31.56769450660329\n        ],\n        [\n          -7.347508279024986,\n          -29.018296180842185\n        ],\n        [\n          -6.003119353680958,\n          -26.39334786674169\n        ],\n        [\n          -4.78399593936067,\n          -23.696669078373624\n        ],\n        [\n          -3.6939866511954946,\n          -20.932086605074673\n        ],\n        [\n          -2.7368964527273523,\n          -18.103423598548964\n        ],\n        [\n          -1.9165594085579771,\n          -15.214510485765711\n        ],\n        [\n          -1.236795032758912,\n          -12.269166780796589\n        ],\n        [\n          -0.7014301146669819,\n          -9.271219272978236\n        ],\n        [\n          -0.3142987188836215,\n          -6.224491114014973\n        ],\n        [\n          -0.07920580895081564,\n          -3.132809093243284\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 893,\n      \"versionNonce\": 780202073,\n      \"isDeleted\": false,\n      \"id\": \"po9WVptfybkUevzcn3VKR\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 942.7271169481343,\n      \"y\": 361.1495680738228,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 16.25669218248767,\n      \"height\": 16.256692182487665,\n      \"seed\": 2058091769,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          -1.638686122205307,\n          0.16510849924087168\n        ],\n        [\n          -3.164802070634858,\n          0.6386700420193787\n        ],\n        [\n          -4.5457019128724845,\n          1.3880368771031326\n        ],\n        [\n          -5.7487378976858,\n          2.3805612532597507\n        ],\n        [\n          -6.741262273842411,\n          3.583595419256838\n        ],\n        [\n          -7.49062910892617,\n          4.964495261494463\n        ],\n        [\n          -7.964190651704678,\n          6.490613028740235\n        ],\n        [\n          -8.129299150945547,\n          8.129297332129324\n        ],\n        [\n          -7.964190651704676,\n          9.767214095071607\n        ],\n        [\n          -7.49062910892617,\n          11.292793492714885\n        ],\n        [\n          -6.7412622738424055,\n          12.673347759869824\n        ],\n        [\n          -5.7487378976858,\n          13.876189131347106\n        ],\n        [\n          -4.545701912872482,\n          14.868629841957384\n        ],\n        [\n          -3.1648020706348587,\n          15.61798212651134\n        ],\n        [\n          -1.638686122205308,\n          16.091565495084552\n        ],\n        [\n          1.7763568394002505e-15,\n          16.256692182487665\n        ],\n        [\n          1.6380568117915821,\n          16.09156549508455\n        ],\n        [\n          3.163699868002724,\n          15.61798212651134\n        ],\n        [\n          4.544261410422562,\n          14.868629841957382\n        ],\n        [\n          5.747070043207801,\n          13.876189131347104\n        ],\n        [\n          6.739456189331349,\n          12.673347759869824\n        ],\n        [\n          7.488752090582334,\n          11.292793492714887\n        ],\n        [\n          7.962288169933693,\n          9.767214095071603\n        ],\n        [\n          8.12739303154212,\n          8.129297332129322\n        ],\n        [\n          7.9622881699336965,\n          6.490613028740235\n        ],\n        [\n          7.488752090582338,\n          4.964495261494464\n        ],\n        [\n          6.739456189331345,\n          3.583595419256838\n        ],\n        [\n          5.747070043207799,\n          2.38056125325975\n        ],\n        [\n          4.544261410422566,\n          1.388036877103133\n        ],\n        [\n          3.163699868002724,\n          0.6386700420193778\n        ],\n        [\n          1.638056811791583,\n          0.16510849924087168\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 896,\n      \"versionNonce\": 713530807,\n      \"isDeleted\": false,\n      \"id\": \"DkgmBi5yRenA04XT30erv\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1000.7598297748109,\n      \"y\": 398.09043493470045,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 16.215154057549217,\n      \"height\": 16.213546224006635,\n      \"seed\": 1374942681,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          -1.3360296459756202,\n          0.9623211139301532\n        ],\n        [\n          -2.4206261370562427,\n          2.1352756972040563\n        ],\n        [\n          -3.2417707356294065,\n          3.4742809265231953\n        ],\n        [\n          -3.7874592546124575,\n          4.934739428059273\n        ],\n        [\n          -4.045658405863139,\n          6.47205382798396\n        ],\n        [\n          -4.004364002298788,\n          8.041641302998759\n        ],\n        [\n          -3.6515427557771476,\n          9.59889720401046\n        ],\n        [\n          -2.9751832039506634,\n          11.099238707720572\n        ],\n        [\n          -2.0136478186295586,\n          12.435377482669669\n        ],\n        [\n          -0.8412534307528468,\n          13.519995799544983\n        ],\n        [\n          0.4974171363809585,\n          14.34108947126386\n        ],\n        [\n          1.957766508943548,\n          14.886690687068146\n        ],\n        [\n          3.495190037841721,\n          15.144809810404922\n        ],\n        [\n          5.065112175041857,\n          15.103464479986293\n        ],\n        [\n          6.622928271450757,\n          14.750657783994443\n        ],\n        [\n          8.124048228505005,\n          14.074421911671243\n        ],\n        [\n          9.460056048685919,\n          13.112886526350135\n        ],\n        [\n          10.544601612912253,\n          11.940477587943622\n        ],\n        [\n          11.365695284631123,\n          10.601792470280017\n        ],\n        [\n          11.911325601494996,\n          9.141413996657825\n        ],\n        [\n          12.16949565168608,\n          7.60392499037556\n        ],\n        [\n          12.128208523386622,\n          6.033922825261546\n        ],\n        [\n          11.775452754249084,\n          4.475990324614276\n        ],\n        [\n          11.099231432455666,\n          2.9747103117322586\n        ],\n        [\n          10.137579642896181,\n          1.6395027706901768\n        ],\n        [\n          8.964894244423526,\n          0.5555683287153252\n        ],\n        [\n          7.625874464574592,\n          -0.26511065290433367\n        ],\n        [\n          6.1652122556213556,\n          -0.8105445376159328\n        ],\n        [\n          4.627599569835823,\n          -1.0687364136017146\n        ],\n        [\n          3.0577283594899773,\n          -1.02770391957371\n        ],\n        [\n          1.5002978521207062,\n          -0.6754574189790601\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 895,\n      \"versionNonce\": 1502838073,\n      \"isDeleted\": false,\n      \"id\": \"QNs5OGimBIo0YQ33pvkdw\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 960.3822405424527,\n      \"y\": 369.27886540595284,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 20.543527438555024,\n      \"height\": 58.75647982339908,\n      \"seed\": 1938412217,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0.046296148182129904,\n          -1.4945867691753179\n        ],\n        [\n          0.1833585012389647,\n          -2.964521303241786\n        ],\n        [\n          0.7187852590825647,\n          -5.8194953052731755\n        ],\n        [\n          1.5843053359046335,\n          -8.543078023236177\n        ],\n        [\n          2.7579401564465535,\n          -11.113418199007896\n        ],\n        [\n          4.217718420714598,\n          -13.508675487362776\n        ],\n        [\n          5.941665191082626,\n          -15.70699499254549\n        ],\n        [\n          7.907801892292,\n          -17.68653636933051\n        ],\n        [\n          10.094157224348978,\n          -19.425448359594895\n        ],\n        [\n          4.151902736809587,\n          -29.37799982795789\n        ],\n        [\n          4.151902736809587,\n          -29.37799982795789\n        ],\n        [\n          1.5730977903283758,\n          -27.48021787810315\n        ],\n        [\n          -0.8202170022986,\n          -25.36197721365912\n        ],\n        [\n          -3.0131237103967656,\n          -23.03810482448914\n        ],\n        [\n          -4.990700765659165,\n          -20.52344225098627\n        ],\n        [\n          -6.738030237411219,\n          -17.83282012064629\n        ],\n        [\n          -8.24019965142708,\n          -14.981072698597426\n        ],\n        [\n          -9.482285620583536,\n          -11.983037887600318\n        ],\n        [\n          -10.449370214206038,\n          -8.853546315150716\n        ],\n        [\n          -9.531801073483289,\n          -8.018720580935769\n        ],\n        [\n          -8.709272355763161,\n          -7.089618326532553\n        ],\n        [\n          -7.990201542533335,\n          -6.074547904455229\n        ],\n        [\n          -7.38300247764899,\n          -4.981817667217991\n        ],\n        [\n          -6.896089004965368,\n          -3.81973596733502\n        ],\n        [\n          -6.537873149521426,\n          -2.5966147949529446\n        ],\n        [\n          -6.316774211621066,\n          -1.3207588649534974\n        ],\n        [\n          -6.241206035119497,\n          -0.00047652985085688826\n        ],\n        [\n          -6.316774211621065,\n          1.3191801324705006\n        ],\n        [\n          -6.537873149521426,\n          2.59457044551644\n        ],\n        [\n          -6.89608900496537,\n          3.8173678686105275\n        ],\n        [\n          -7.38300247764899,\n          4.979256773973689\n        ],\n        [\n          -7.990201542533329,\n          6.071906983297043\n        ],\n        [\n          -8.709272355763163,\n          7.0869883182716995\n        ],\n        [\n          -9.531801073483289,\n          8.016185151118627\n        ],\n        [\n          -10.44937021420604,\n          8.85116002826399\n        ],\n        [\n          -9.48322412975545,\n          11.98132092508425\n        ],\n        [\n          -8.241809303785892,\n          14.97993775727324\n        ],\n        [\n          -6.740041848155682,\n          17.832176259702777\n        ],\n        [\n          -4.992846968804235,\n          20.52320216724461\n        ],\n        [\n          -3.015135321141228,\n          23.038181214770574\n        ],\n        [\n          -0.8218248358411877,\n          25.36227186188752\n        ],\n        [\n          1.5721592811564573,\n          27.480654393997064\n        ],\n        [\n          4.151902736809584,\n          29.378479995441197\n        ],\n        [\n          10.094157224348985,\n          19.423065710340612\n        ],\n        [\n          10.094157224348985,\n          19.423065710340612\n        ],\n        [\n          7.907801892291995,\n          17.684961274479953\n        ],\n        [\n          5.941665191082625,\n          15.706060121006029\n        ],\n        [\n          4.217718420714604,\n          13.508217145674164\n        ],\n        [\n          2.757940156446555,\n          11.113301794769523\n        ],\n        [\n          1.584305335904634,\n          8.543161688782508\n        ],\n        [\n          0.7187852590825647,\n          5.819658998733398\n        ],\n        [\n          0.18335850123896424,\n          2.9646558956424114\n        ],\n        [\n          0.046296148182129904,\n          1.4946667970892022\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 897,\n      \"versionNonce\": 1498992343,\n      \"isDeleted\": false,\n      \"id\": \"-f2Rh5dGjAdREvQlwi6Kj\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 984.1226557886606,\n      \"y\": 345.5360675104861,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 50.87606566581782,\n      \"height\": 33.20282484308948,\n      \"seed\": 605098905,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          2.2977432752867406,\n          0.1097510086275586\n        ],\n        [\n          4.533206645409167,\n          0.4322816897439514\n        ],\n        [\n          6.696317506115195,\n          0.9574939756699439\n        ],\n        [\n          8.776999615520289,\n          1.675297073991198\n        ],\n        [\n          10.765162181210117,\n          2.575592917028489\n        ],\n        [\n          12.650728961300139,\n          3.6482943499999276\n        ],\n        [\n          14.423630989170718,\n          4.88330330522628\n        ],\n        [\n          16.07378474767242,\n          6.270525352660773\n        ],\n        [\n          17.591099444390903,\n          7.799869699889078\n        ],\n        [\n          18.96551338797144,\n          9.461241916864399\n        ],\n        [\n          20.186935785999708,\n          11.244547573539936\n        ],\n        [\n          21.245297671856026,\n          13.139695877501378\n        ],\n        [\n          22.130508253126113,\n          15.136588761069504\n        ],\n        [\n          22.832498563190278,\n          17.225131794197523\n        ],\n        [\n          23.341185084899166,\n          19.395237822103553\n        ],\n        [\n          23.646484301103275,\n          21.63680877710834\n        ],\n        [\n          35.22776023520919,\n          21.46611651205781\n        ],\n        [\n          35.22776023520919,\n          21.46611651205781\n        ],\n        [\n          34.86003197091034,\n          18.153946675637258\n        ],\n        [\n          34.19355222881611,\n          14.941804456307336\n        ],\n        [\n          33.2428933645184,\n          11.843887533517583\n        ],\n        [\n          32.022642284138804,\n          8.874404499614956\n        ],\n        [\n          30.547385893799017,\n          6.047556671681482\n        ],\n        [\n          28.831703824355806,\n          3.3775490044316516\n        ],\n        [\n          26.890175706665907,\n          0.8785791773150233\n        ],\n        [\n          24.73738844685095,\n          -1.4351442173214668\n        ],\n        [\n          23.55782792304913,\n          -1.060879127511246\n        ],\n        [\n          22.34460474856158,\n          -0.8158154670349589\n        ],\n        [\n          21.109039235570478,\n          -0.7029106310738591\n        ],\n        [\n          19.862429870463338,\n          -0.7251402029714757\n        ],\n        [\n          18.616089690157438,\n          -0.8854688531739825\n        ],\n        [\n          17.381324456305194,\n          -1.1868612521275423\n        ],\n        [\n          16.169447205823868,\n          -1.6322857079107829\n        ],\n        [\n          14.991763700365887,\n          -2.224710528602327\n        ],\n        [\n          13.887160230814164,\n          -2.949137755613741\n        ],\n        [\n          12.893642780998903,\n          -3.777092002131984\n        ],\n        [\n          12.014186934263599,\n          -4.6972311301801515\n        ],\n        [\n          11.251804650276277,\n          -5.698198451251574\n        ],\n        [\n          10.609486062910259,\n          -6.768653646185575\n        ],\n        [\n          10.09022130603886,\n          -7.8972436641079256\n        ],\n        [\n          9.697015064065194,\n          -9.072624548225507\n        ],\n        [\n          9.432850195597677,\n          -10.283445066480297\n        ],\n        [\n          7.111029431129076,\n          -10.84241094390326\n        ],\n        [\n          4.75948920954977,\n          -11.243225294144628\n        ],\n        [\n          2.386290524367385,\n          -11.484793189837148\n        ],\n        [\n          -0.0004765298508546678,\n          -11.566016065981145\n        ],\n        [\n          -2.0317523153296806,\n          -11.509409048621496\n        ],\n        [\n          -4.051336750116484,\n          -11.336195904283603\n        ],\n        [\n          -6.054315392772262,\n          -11.04752066837277\n        ],\n        [\n          -8.035784714755394,\n          -10.644531013926734\n        ],\n        [\n          -9.990826636994429,\n          -10.128372795167026\n        ],\n        [\n          -11.914537630947708,\n          -9.5001936851314\n        ],\n        [\n          -13.801999617543814,\n          -8.761141356857612\n        ],\n        [\n          -15.648305430608632,\n          -7.912359845750952\n        ],\n        [\n          -10.000710084359147,\n          2.2084976007758312\n        ],\n        [\n          -10.000710084359147,\n          2.2084976007758312\n        ],\n        [\n          -7.602539052412382,\n          1.2479189127888883\n        ],\n        [\n          -5.121353610340339,\n          0.5563249562647745\n        ],\n        [\n          -2.5796707030041466,\n          0.13869565002656636\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 897,\n      \"versionNonce\": 545353241,\n      \"isDeleted\": false,\n      \"id\": \"07QbQy7SlS7FR5mHQ_OcP\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 984.1226557886631,\n      \"y\": 393.01975718201027,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 50.87654219566864,\n      \"height\": 33.206164189677914,\n      \"seed\": 1203583097,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          -2.5795433858684236,\n          -0.1387756779404492\n        ],\n        [\n          -5.121098976068896,\n          -0.5564340852382554\n        ],\n        [\n          -7.602164376270109,\n          -1.247998940702777\n        ],\n        [\n          -10.000229916875844,\n          -2.208501238408282\n        ],\n        [\n          -15.647828900757778,\n          7.911406786049239\n        ],\n        [\n          -15.647828900757778,\n          7.911406786049239\n        ],\n        [\n          -13.801704969315425,\n          8.761114074614227\n        ],\n        [\n          -11.91433028589811,\n          9.500964863210642\n        ],\n        [\n          -9.990630204842168,\n          10.129824210514279\n        ],\n        [\n          -8.035526442851499,\n          10.646535349406285\n        ],\n        [\n          -6.053944354262443,\n          11.049948788032667\n        ],\n        [\n          -4.050802018146447,\n          11.338907759274544\n        ],\n        [\n          -2.0310211512073755,\n          11.512262771277966\n        ],\n        [\n          0.00047652985085289146,\n          11.568878882718728\n        ],\n        [\n          2.387287235658486,\n          11.487526870622787\n        ],\n        [\n          4.760449544516376,\n          11.245362403208581\n        ],\n        [\n          7.111829710267919,\n          10.843469494946007\n        ],\n        [\n          9.433323087816074,\n          10.282968536629443\n        ],\n        [\n          9.69750978207829,\n          9.072262603796805\n        ],\n        [\n          10.09075967564135,\n          7.8971690926427085\n        ],\n        [\n          10.610068084102135,\n          6.7689282874354975\n        ],\n        [\n          11.252401221997959,\n          5.698795022973254\n        ],\n        [\n          12.014761680190574,\n          4.6980095835243\n        ],\n        [\n          12.894115673217303,\n          3.7778268038867386\n        ],\n        [\n          13.887458516675004,\n          2.949479693063979\n        ],\n        [\n          14.99176370036589,\n          2.2242376363839167\n        ],\n        [\n          16.170283861287206,\n          1.6308524807257605\n        ],\n        [\n          17.382597627662435,\n          1.1849805961512585\n        ],\n        [\n          18.617471990488166,\n          0.8835227198136106\n        ],\n        [\n          19.86368121602589,\n          0.7234159651905117\n        ],\n        [\n          21.109999570537106,\n          0.7015537941702714\n        ],\n        [\n          22.345208595548172,\n          0.8148660449656919\n        ],\n        [\n          23.558082557320592,\n          1.0602680052597648\n        ],\n        [\n          24.737388446850964,\n          1.4346676874705953\n        ],\n        [\n          26.89031393669896,\n          -0.8790557071658753\n        ],\n        [\n          28.83191480703786,\n          -3.378021896650049\n        ],\n        [\n          30.547647803335387,\n          -6.048036839164791\n        ],\n        [\n          32.02294056999967,\n          -8.874884667098264\n        ],\n        [\n          33.24324985249844,\n          -11.844364063368438\n        ],\n        [\n          34.19401784576962,\n          -14.942280986158185\n        ],\n        [\n          34.86069402001611,\n          -18.15442684312056\n        ],\n        [\n          35.228713294910854,\n          -21.46659304190866\n        ],\n        [\n          23.64410528948141,\n          -21.63728530695919\n        ],\n        [\n          23.64410528948141,\n          -21.63728530695919\n        ],\n        [\n          23.33922076337652,\n          -19.395165069454553\n        ],\n        [\n          22.830919830707288,\n          -17.22465526434667\n        ],\n        [\n          22.129271458093335,\n          -15.135824858255177\n        ],\n        [\n          21.244359162684127,\n          -13.138764643594378\n        ],\n        [\n          20.18625918636411,\n          -11.243543586983932\n        ],\n        [\n          18.965055046282824,\n          -9.460252480838186\n        ],\n        [\n          17.59083025958965,\n          -7.79896029177675\n        ],\n        [\n          16.073661068169137,\n          -6.269750536949084\n        ],\n        [\n          14.42363098917071,\n          -4.882699458239705\n        ],\n        [\n          12.650816264478923,\n          -3.6478905727980555\n        ],\n        [\n          10.76530041124319,\n          -2.5754001225086762\n        ],\n        [\n          8.77715967134806,\n          -1.6753043492560993\n        ],\n        [\n          6.696484837207861,\n          -0.957686770189754\n        ],\n        [\n          4.533344875442237,\n          -0.43262362719418457\n        ],\n        [\n          2.2978233032006212,\n          -0.11019116215392355\n        ],\n        [\n          0,\n          -0.0004728922184047496\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 896,\n      \"versionNonce\": 891739127,\n      \"isDeleted\": false,\n      \"id\": \"cKx3lSU7PeZafbwDHjet1\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1000.7569633204448,\n      \"y\": 340.46252694106204,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 16.214310126820983,\n      \"height\": 16.21424464943689,\n      \"seed\": 1884406105,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          1.5011417828489422,\n          0.6762249594258607\n        ],\n        [\n          3.059008806112128,\n          1.0292862896891504\n        ],\n        [\n          4.628989145431456,\n          1.0710863241639539\n        ],\n        [\n          6.166470876448814,\n          0.8135237585919004\n        ],\n        [\n          7.6268420748061025,\n          0.26850092634707323\n        ],\n        [\n          8.965505366675004,\n          -0.5520798391964554\n        ],\n        [\n          10.137841552432532,\n          -1.6363234799294961\n        ],\n        [\n          11.09923870772056,\n          -2.9723203872130677\n        ],\n        [\n          11.775736489580115,\n          -4.473467626510686\n        ],\n        [\n          12.128928774611584,\n          -6.031372844914586\n        ],\n        [\n          12.170746997248635,\n          -7.601456856758716\n        ],\n        [\n          11.913122591924951,\n          -9.13914593282569\n        ],\n        [\n          11.367994268339086,\n          -10.59986270626565\n        ],\n        [\n          10.547293460924724,\n          -11.939031629045012\n        ],\n        [\n          9.462958879380459,\n          -13.112075334313921\n        ],\n        [\n          8.126914682875036,\n          -14.07441645522255\n        ],\n        [\n          6.625787450555896,\n          -14.74989206236384\n        ],\n        [\n          5.067934977822506,\n          -15.102156751120749\n        ],\n        [\n          3.4979109869137925,\n          -15.143158325272937\n        ],\n        [\n          1.9602692000686606,\n          -14.884844588600105\n        ],\n        [\n          0.4995851653207355,\n          -14.339157888433272\n        ],\n        [\n          -0.8395873950910682,\n          -13.518046028552156\n        ],\n        [\n          -2.0127020341927455,\n          -12.4334549939202\n        ],\n        [\n          -2.9751759286857657,\n          -11.097328950684679\n        ],\n        [\n          -3.6504805671019556,\n          -9.596836485227946\n        ],\n        [\n          -4.0026106634582295,\n          -8.03949328103745\n        ],\n        [\n          -4.043563129572347,\n          -6.469911262471312\n        ],\n        [\n          -3.7853057762024767,\n          -4.9327096291525585\n        ],\n        [\n          -3.2398427904312856,\n          -3.472502124255492\n        ],\n        [\n          -2.419141983016932,\n          -2.1339043097706747\n        ],\n        [\n          -1.3352002657771815,\n          -0.9615317476886582\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"id\": \"ANpLlH9b4bpHbYI2jx9SY\",\n      \"type\": \"text\",\n      \"x\": 931.4255845647491,\n      \"y\": 438.9225098516119,\n      \"width\": 100.18808099312358,\n      \"height\": 16.618264290489687,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 535973721,\n      \"version\": 622,\n      \"versionNonce\": 977158905,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"Ubuntu jumpbox\",\n      \"fontSize\": 13.294611432391749,\n      \"fontFamily\": 1,\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 11,\n      \"containerId\": null,\n      \"originalText\": \"Ubuntu jumpbox\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"id\": \"yDqC0vP8PztDo8wtSuXpT\",\n      \"type\": \"text\",\n      \"x\": 935.6556882023284,\n      \"y\": 457.6558259608914,\n      \"width\": 92.9957420544854,\n      \"height\": 16.618264290489687,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 352397047,\n      \"version\": 630,\n      \"versionNonce\": 1106658583,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"192.168.56.100\",\n      \"fontSize\": 13.294611432391749,\n      \"fontFamily\": 1,\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 11,\n      \"containerId\": null,\n      \"originalText\": \"192.168.56.100\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"id\": \"YVuKEDAbE4-UKuRyM2zKo\",\n      \"type\": \"rectangle\",\n      \"x\": 846.1345092947488,\n      \"y\": 378.3641412145678,\n      \"width\": 74.90211824997922,\n      \"height\": 89.18980554621794,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"seed\": 1126937945,\n      \"version\": 187,\n      \"versionNonce\": 255560247,\n      \"isDeleted\": false,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 2105,\n      \"versionNonce\": 1002608825,\n      \"isDeleted\": false,\n      \"id\": \"q1Z162M8jlXNPgOu7uE6d\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 853.6037927731572,\n      \"y\": 423.29626201872316,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#364fc7\",\n      \"width\": 57.21135267636953,\n      \"height\": 32.14120936874693,\n      \"seed\": 190491641,\n      \"groupIds\": [\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"5H_8bJE7xZuZg1sOmEEq6\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"cMIoGo9YKI2HKyZ8oisu_\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 12.856483747498771,\n      \"fontFamily\": 1,\n      \"text\": \"Public IP\\nAddress\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Public IP\\nAddress\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 27\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 946,\n      \"versionNonce\": 1239100247,\n      \"isDeleted\": false,\n      \"id\": \"001M3swpLRvx_vtPiGUgm\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 860.1435827743173,\n      \"y\": 395.0150150769979,\n      \"strokeColor\": \"#59b4d9\",\n      \"backgroundColor\": \"#59b4d9\",\n      \"width\": 44.9976931162457,\n      \"height\": 25.712967494997535,\n      \"seed\": 1458881753,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"KZNLIFHdFxYfL0x7VkmSa\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 674,\n      \"versionNonce\": 893458841,\n      \"isDeleted\": false,\n      \"id\": \"17KUh3liZT_XnKQSVDrOf\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 860.3173190411758,\n      \"y\": 388.7605094701064,\n      \"strokeColor\": \"#b3b4b5\",\n      \"backgroundColor\": \"#b3b4b5\",\n      \"width\": 44.302748048813505,\n      \"height\": 11.119121078917706,\n      \"seed\": 1570292153,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 684,\n      \"versionNonce\": 237611127,\n      \"isDeleted\": false,\n      \"id\": \"ut7j7xP15-glEg-Yxv_n1\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 4,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 875.9535830584045,\n      \"y\": 393.10391614155844,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#59b4d9\",\n      \"width\": 25.01802242756535,\n      \"height\": 0.1737362668581942,\n      \"seed\": 1818895001,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          25.01802242756535,\n          0.1737362668581942\n        ]\n      ]\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 697,\n      \"versionNonce\": 16547449,\n      \"isDeleted\": false,\n      \"id\": \"PYbhZtBfC_dCfC6AVPOTU\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 4,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 864.3893749136021,\n      \"y\": 391.63036930175906,\n      \"strokeColor\": \"#59b4d9\",\n      \"backgroundColor\": \"#59b4d9\",\n      \"width\": 4.72882160827512,\n      \"height\": 4.35938242012891,\n      \"seed\": 1612474233,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"KZNLIFHdFxYfL0x7VkmSa\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 2702,\n      \"versionNonce\": 2045477271,\n      \"isDeleted\": false,\n      \"id\": \"KZNLIFHdFxYfL0x7VkmSa\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 869.7228699204347,\n      \"y\": 393.67208308542865,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#59b4d9\",\n      \"width\": 6.317383983935549,\n      \"height\": 0.01084707764919542,\n      \"seed\": 854790233,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"PYbhZtBfC_dCfC6AVPOTU\",\n        \"focus\": 0.06564010348681451,\n        \"gap\": 1\n      },\n      \"endBinding\": {\n        \"elementId\": \"001M3swpLRvx_vtPiGUgm\",\n        \"gap\": 3.2170976246970895,\n        \"focus\": -0.9489632626919575\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -6.317383983935549,\n          -0.01084707764919542\n        ]\n      ]\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 635,\n      \"versionNonce\": 230180697,\n      \"isDeleted\": false,\n      \"id\": \"VwmvkBiL22cDVY2npZqLz\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 870.9494747412251,\n      \"y\": 409.51150914762565,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 4.489565753094957,\n      \"height\": 3.979387826606734,\n      \"seed\": 1254202681,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 661,\n      \"versionNonce\": 2119513783,\n      \"isDeleted\": false,\n      \"id\": \"sGgvirVMpIGaiCMIYX61X\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 880.5408197592,\n      \"y\": 409.6645625255721,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 4.489565753094957,\n      \"height\": 3.979387826606734,\n      \"seed\": 116100633,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 676,\n      \"versionNonce\": 633861177,\n      \"isDeleted\": false,\n      \"id\": \"F5t-e2OvVH4PppXZ1meYU\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 889.5199512653899,\n      \"y\": 409.25642018438174,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 4.489565753094957,\n      \"height\": 3.979387826606734,\n      \"seed\": 241459961,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 460,\n      \"versionNonce\": 1549578489,\n      \"isDeleted\": false,\n      \"id\": \"HBV6GFmKFga3QlsG4jsS3\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 533.5656031965165,\n      \"y\": 620.4959025516371,\n      \"strokeColor\": \"#343a40\",\n      \"backgroundColor\": \"#ced4da\",\n      \"width\": 77.95193665608433,\n      \"height\": 51.96795777072297,\n      \"seed\": 751293977,\n      \"groupIds\": [\n        \"NQHJFAj9KunAAW5Y2Plvz\",\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"e1j7blQ1XneZeqq8jPxjG\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 570,\n      \"versionNonce\": 700299031,\n      \"isDeleted\": false,\n      \"id\": \"ogVX7dRLL-_fX6DjLxMJD\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 526.1307933872436,\n      \"y\": 678.2481726383328,\n      \"strokeColor\": \"#343a40\",\n      \"backgroundColor\": \"#ced4da\",\n      \"width\": 91.5950397887827,\n      \"height\": 12.537724077551774,\n      \"seed\": 1098361593,\n      \"groupIds\": [\n        \"NQHJFAj9KunAAW5Y2Plvz\",\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 739,\n      \"versionNonce\": 594422233,\n      \"isDeleted\": false,\n      \"id\": \"sHLf8lm2U8SAREHuN3VXO\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 593.6608588706778,\n      \"y\": 682.839451878,\n      \"strokeColor\": \"#343a40\",\n      \"backgroundColor\": \"#343a40\",\n      \"width\": 16.412842239236777,\n      \"height\": 3.1638622965655476,\n      \"seed\": 1595532249,\n      \"groupIds\": [\n        \"NQHJFAj9KunAAW5Y2Plvz\",\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 841,\n      \"versionNonce\": 826588215,\n      \"isDeleted\": false,\n      \"id\": \"tRKiaOkCLePOfA4s2Ro11\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 564.5827570194542,\n      \"y\": 673.2742867953597,\n      \"strokeColor\": \"#343a40\",\n      \"backgroundColor\": \"#343a40\",\n      \"width\": 16.412842239236777,\n      \"height\": 3.1638622965655476,\n      \"seed\": 29491385,\n      \"groupIds\": [\n        \"NQHJFAj9KunAAW5Y2Plvz\",\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1168,\n      \"versionNonce\": 2141030073,\n      \"isDeleted\": false,\n      \"id\": \"iyDGxVpbf7o0hyIpg-1CQ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 540.2601359608269,\n      \"y\": 626.5080776804144,\n      \"strokeColor\": \"#343a40\",\n      \"backgroundColor\": \"#343a40\",\n      \"width\": 64.66238398560861,\n      \"height\": 40.55831658431314,\n      \"seed\": 1460896153,\n      \"groupIds\": [\n        \"NQHJFAj9KunAAW5Y2Plvz\",\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"cMIoGo9YKI2HKyZ8oisu_\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"id\": \"QDqW1cWW2zpHMG_bfkKqs\",\n      \"type\": \"text\",\n      \"x\": 541.9762478323058,\n      \"y\": 696.0719953022088,\n      \"width\": 59.904130898657954,\n      \"height\": 33.51846580833981,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 1274093559,\n      \"version\": 83,\n      \"versionNonce\": 2012093783,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"User\",\n      \"fontSize\": 26.81477264667185,\n      \"fontFamily\": 1,\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 23,\n      \"containerId\": null,\n      \"originalText\": \"User\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"id\": \"cMIoGo9YKI2HKyZ8oisu_\",\n      \"type\": \"arrow\",\n      \"x\": 568.7540146490983,\n      \"y\": 616.5532261351875,\n      \"width\": 269.81538376558444,\n      \"height\": 187.28361931964116,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 1441062425,\n      \"version\": 287,\n      \"versionNonce\": 554588791,\n      \"isDeleted\": false,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          20.103891339396455,\n          -181.99312159874734\n        ],\n        [\n          269.81538376558444,\n          -187.28361931964116\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"iyDGxVpbf7o0hyIpg-1CQ\",\n        \"focus\": -0.20760313214837897,\n        \"gap\": 9.954851545226916\n      },\n      \"endBinding\": {\n        \"elementId\": \"q1Z162M8jlXNPgOu7uE6d\",\n        \"focus\": 0.6609140883548593,\n        \"gap\": 15.034394358474572\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\"\n    },\n    {\n      \"id\": \"vAokcSMGJD8JOjx_pqrs_\",\n      \"type\": \"text\",\n      \"x\": 568.8255276482058,\n      \"y\": 487.4650817453783,\n      \"width\": 31.599960327148438,\n      \"height\": 25,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 1763285657,\n      \"version\": 95,\n      \"versionNonce\": 689042777,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"ssh\",\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 18,\n      \"containerId\": null,\n      \"originalText\": \"ssh\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"id\": \"5EnmiI-P42lyF3ONrbFTZ\",\n      \"type\": \"arrow\",\n      \"x\": 1074.5255967665473,\n      \"y\": 396.5726756511387,\n      \"width\": 540.2534995094286,\n      \"height\": 37.04769399014752,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 880750297,\n      \"version\": 183,\n      \"versionNonce\": 1830676215,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358774,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          436.99511174582904,\n          27.420643387404695\n        ],\n        [\n          540.2534995094286,\n          -9.627050602742829\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n        \"focus\": -0.0338306515364628,\n        \"gap\": 11.630959869796413\n      },\n      \"endBinding\": {\n        \"elementId\": \"yN10xzW1r35OxRKCg_xMP\",\n        \"focus\": -0.7474214780713206,\n        \"gap\": 11.747584697238977\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"6AoiEoK2dW91-YLQdsgSp\",\n      \"type\": \"arrow\",\n      \"x\": 1076.6417958549048,\n      \"y\": 397.5266204901835,\n      \"width\": 475.9464130599106,\n      \"height\": 83.6128846594089,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 252254455,\n      \"version\": 221,\n      \"versionNonce\": 1766942713,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358774,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          385.14823408106986,\n          31.74298632536295\n        ],\n        [\n          475.9464130599106,\n          83.6128846594089\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n        \"focus\": -0.044719394158033186,\n        \"gap\": 13.747158958153875\n      },\n      \"endBinding\": {\n        \"elementId\": \"TqllulP3IVZg-yrzbF9fj\",\n        \"focus\": 6.983484088284758,\n        \"gap\": 9.768019090227178\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"l8S7i1jyyXiaBDgV1tqr5\",\n      \"type\": \"arrow\",\n      \"x\": 1075.583696310726,\n      \"y\": 394.46079616958536,\n      \"width\": 337.5337545930254,\n      \"height\": 28.57756888456061,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 1790548057,\n      \"version\": 163,\n      \"versionNonce\": 483651607,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358774,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          281.45447875155105,\n          20.004298219192364\n        ],\n        [\n          337.5337545930254,\n          -8.573270665368245\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n        \"focus\": -0.06464881033211498,\n        \"gap\": 12.689059413975144\n      },\n      \"endBinding\": {\n        \"elementId\": \"rWHSJYGi-z3aEn2JRzgPA\",\n        \"focus\": -0.5258663147656351,\n        \"gap\": 4.122175285811579\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"cKxlt68orMI7e-h7oVKRx\",\n      \"type\": \"arrow\",\n      \"x\": 1075.583696310726,\n      \"y\": 397.5266204901834,\n      \"width\": 225.3752029100765,\n      \"height\": 84.6479635343012,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 1223543639,\n      \"version\": 234,\n      \"versionNonce\": 1051984089,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358774,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          168.2378275244232,\n          17.047159322880105\n        ],\n        [\n          225.3752029100765,\n          84.6479635343012\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n        \"focus\": -0.06174908744841584,\n        \"gap\": 12.689059413975144\n      },\n      \"endBinding\": {\n        \"elementId\": \"5D9sQqWIBXUO5ZOBf3kUj\",\n        \"focus\": 5.612789308193268,\n        \"gap\": 10.303516029969497\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"SAhg2CJFAfFnLulnaYOt8\",\n      \"type\": \"arrow\",\n      \"x\": 1075.583696310726,\n      \"y\": 396.4685209460048,\n      \"width\": 138.61104028741784,\n      \"height\": 22.22009042775403,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 180038489,\n      \"version\": 136,\n      \"versionNonce\": 1757623159,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954361715,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          90.99656079937358,\n          6.348597265072613\n        ],\n        [\n          138.61104028741784,\n          -15.871493162681418\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n        \"focus\": -0.04250656774231881,\n        \"gap\": 12.689059413975144\n      },\n      \"endBinding\": {\n        \"elementId\": \"FLuHTL7vlxV7h0XCrkNXu\",\n        \"focus\": -0.4543785686983688,\n        \"gap\": 1\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"yefDBe5_BH_bWFBYnLcdl\",\n      \"type\": \"line\",\n      \"x\": 561.3473178398472,\n      \"y\": 117.13024128281134,\n      \"width\": 74.06696809251343,\n      \"height\": 0,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"MeV0d-fYHW8nH43woqy6_\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 1549472025,\n      \"version\": 182,\n      \"versionNonce\": 495260793,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954416242,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          74.06696809251343,\n          0\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"AWeMRml6oGOy65lV5ByOH\",\n      \"type\": \"text\",\n      \"x\": 655.0375165897938,\n      \"y\": 101.25874812012981,\n      \"width\": 113.119873046875,\n      \"height\": 25,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"MeV0d-fYHW8nH43woqy6_\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 813013239,\n      \"version\": 148,\n      \"versionNonce\": 945769367,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954416242,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"provisionning\",\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 18,\n      \"containerId\": null,\n      \"originalText\": \"provisionning\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    }\n  ],\n  \"appState\": {\n    \"gridSize\": null,\n    \"viewBackgroundColor\": \"#ffffff\"\n  },\n  \"files\": {}\n}"
  },
  {
    "path": "docs/mkdocs/docs/changelog.md",
    "content": "# Road Map\n\n## v1\n- [X] SMB share anonymous\n- [X] SMB not signed\n- [X] Responder\n- [X] Zerologon\n- [X] Windows defender\n- [X] ASREPRoast\n- [X] Kerberoasting\n- [X] AD Acl abuse \n- [X] Unconstraint delegation\n- [X] Ntlm relay\n\n## v2\n- [X] Password reuse between computer (PTH)\n- [X] Spray User = Password\n- [X] Password in description\n- [X] Constrained delegation\n- [X] Install MSSQL\n- [X] MSSQL trusted link\n- [X] MSSQL impersonate\n- [X] Install IIS\n- [X] Upload asp app\n- [X] Multiples forest\n- [X] Anonymous RPC user listing\n- [X] Child parent domain\n- [X] Generate certificate and enable ldaps\n- [X] ADCS - ESC 1/2/3/4/6/8\n- [X] Certifry\n- [X] Samaccountname/nopac\n- [X] Petitpotam unauthent\n- [X] Printerbug\n- [X] Drop the mic\n- [X] Shadow credentials\n- [X] Mitm6\n- [X] Add LAPS\n- [X] GPO abuse\n- [X] Add Webdav\n- [X] Add RDP bot\n- [X] Add full proxmox integration\n- [X] Add Gmsa (receipe created)\n- [X] Add azure support\n- [X] Refactoring lab and providers\n- [X] Protected Users\n- [X] Account is sensitive\n- [X] Add PPL\n- [X] Add Gmsa\n- [X] Groups inside groups\n- [X] Shares with secrets (all, sysvol)\n- [X] Sccm (see SCCM lab)\n\n## v3\n- [X] aws support\n- [X] ludus support\n- [X] windows install compatibility\n- [X] extension support\n- [X] multiple instance management\n- [X] extension exchange\n- [X] extension ludus\n- [X] extension elk\n- [X] extension ws01\n- [X] extension exchange add a bot to read mails\n- [X] extension guacamole\n- [X] extension linux VM enrolled\n- [X] ADCS add vulns\n\n## maybe one day if i get the time\n- [ ] new training lab\n- [ ] extension \"life\", add some bots in the lab\n- [ ] extension Xworkstations, to add multiple workstations\n- [ ] extension attackbox\n- [ ] extension VPN\n- [ ] Add Applocker to ws01\n- [ ] Wsus (to add on sccm)\n\n"
  },
  {
    "path": "docs/mkdocs/docs/developers/add_extension.md",
    "content": "# Add an extension\n\n- The extension structure MUST be like this :\n```\nextensions/\n    <extension_name>/\n        ansible/            # mandatory\n            install.yml     # mandatory\n        providers/          # mandatory\n            aws/\n            azure/\n            ludus/\n            proxmox/\n            virtualbox/\n            vmware/\n        inventory           # mandatory\n        extension.json      # mandatory\n```\n## Create Extension.json\n\n- Create the extension.json file\n\n```json\n{\n    \"name\": \"my extension\",\n    \"description\": \"Add an extension to goad lab\",\n    \"machines\": [\n        \"ws02 (myvm.sevenkingdoms.local)\"\n    ],\n    \"compatibility\": [\n        \"GOAD\",\n        \"GOAD-Light\",\n        \"GOAD-Mini\"\n    ],\n    \"impact\": \"blabla\"\n}\n```\n\n## Providers\n\n- If the extension need provisioning (new vm) add in each provider folder the vm(s) needed.\n- Providers follow the following types\n    - Vagrant:\n        - vmware\n        - virtualbox\n    - Terraform:\n        - aws\n        - azure\n        - proxmox\n    - Ludus\n\n\n=== \":simple-vmware: Vmware workstation\"\n    - As an example to add a new box for vmware :\n        - Create the folder `extensions/<extension_name>/providers/vmware/`\n        - Add a file named Vagrantfile\n        - Add the following code for a linux machine  (and change box, ip, name, cpu, ram):\n        ```\n        boxes.append(\n            { :name => \"{{lab_name}}-EXTNAME\",\n            :ip => \"{{ip_range}}.66\",\n            :box => \"bento/ubuntu-22.04\", \n            :os => \"linux\",\n            :cpus => 2,\n            :mem => 4000,\n            :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n            }\n        )\n        ```\n        - Add the following code for a windows machine (and change box, ip, name, cpu, ram):\n        ```\n        # add windows box\n        boxes.append(\n            { :name => \"{{lab_name}}-EXTNAME\",\n                :ip => \"{{ip_range}}.66\",\n                :box => \"mayfly/windows10\",\n                :os => \"windows\",\n                :cpus => 2,\n                :mem => 4000\n            }\n        )\n        ```\n\n=== \":simple-virtualbox: Virtualbox\"\n    - As an example to add a new box for virtualbox :\n        - Create the folder `extensions/<extension_name>/providers/virtualbox/`\n        - Add a file named Vagrantfile\n        - Add the following code for a linux machine  (and change box, ip, name, cpu, ram):\n        ```\n        boxes.append(\n            { :name => \"{{lab_name}}-EXTNAME\",\n            :ip => \"{{ip_range}}.66\",\n            :box => \"bento/ubuntu-22.04\", \n            :os => \"linux\",\n            :cpus => 2,\n            :mem => 4000,\n            :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n            }\n        )\n        ```\n        - Add the following code for a windows machine (and change box, ip, name, cpu, ram):\n        ```\n        # add windows box\n        boxes.append(\n            { :name => \"{{lab_name}}-EXTNAME\",\n                :ip => \"{{ip_range}}.66\",\n                :box => \"mayfly/windows10\",\n                :os => \"windows\",\n                :cpus => 2,\n                :mem => 4000\n            }\n        )\n        ```\n\n=== \":material-microsoft-azure: Azure\"\n    - As an example to add a new box for azure :\n        - Create the folder `extensions/<extension_name>/providers/azure/`\n        - Add a file (linux.tf or windows.tf) depending of the type of vm\n        - For a linux box (linux.tf file) (change box sku, ip, name, box size):\n        ```\n        \"vmname\" = {\n            name               = \"vmname\"\n            linux_sku          = \"22_04-lts-gen2\"\n            linux_version      = \"latest\"\n            private_ip_address = \"{{ip_range}}.51\"\n            password           = \"rootpassword\"\n            size               = \"Standard_B2s\"  # 2cpu/4G\n            }\n        ```\n        - For a windows box (windows.tf file) (change box sku, ip, name, box size):\n        ```\n        \"vmname\" = {\n            name               = \"vmname\"\n            publisher          = \"MicrosoftWindowsServer\"\n            offer              = \"WindowsServer\"\n            windows_sku        = \"2019-Datacenter\"\n            windows_version    = \"17763.4377.230505\"\n            private_ip_address = \"{{ip_range}}.10\"\n            password           = \"goadadmin_password\"\n            size               = \"Standard_B2s\"  # 2cpu/4G\n        }\n        ```\n\n=== \":simple-amazon: Aws\"\n    - As an example to add a new box for aws :\n        - Create the folder `extensions/<extension_name>/providers/aws/`\n        - Add a file (linux.tf or windows.tf) depending of the type of vm\n        - For a linux box (linux.tf file) (change box sku, ip, name, box size):\n        ```\n        \"vmname\" = {\n            name               = \"vmname\"\n            linux_sku          = \"22_04-lts-gen2\"\n            linux_version      = \"latest\"\n            ami                = \"ami-04c332520bd9cedb4\"\n            private_ip_address = \"{{ip_range}}.51\"\n            password           = \"sgdvnkjhdshlsd\"\n            size               = \"t2.medium\"\n        }\n        ```\n        - For a windows box (windows.tf file) (change box sku, ip, name, box size):\n        ```\n        \"vmname\" = {\n            name               = \"vmname\"\n            domain             = \"sevenkingdoms.local\"\n            windows_sku        = \"2019-Datacenter\"\n            ami                = \"ami-018ebfbd6b0a4c605\"\n            instance_type      = \"t2.medium\"\n            private_ip_address = \"{{ip_range}}.21\"\n            password           = \"goadadmin_password\"\n        }\n        ```\n        - Find AMI example :\n        ```\n        aws ec2 describe-images \\\n          --owners \"amazon\" \\\n          --filters \"Name=name,Values=Windows_Server-2019-English-Full-Base*\" \\ \n          --query \"Images[*].{ImageId:ImageId,Name:Name,CreationDate:CreationDate,Description:Description}\" \\\n          --output table\n        ```\n\n=== \":simple-proxmox: Proxmox\"\n    - As an example to add a new box for proxmox :\n        - Create the folder `extensions/<extension_name>/providers/proxmox/`\n        - Add a file (linux.tf or windows.tf) depending of the type of vm\n        - For a linux box (linux.tf file) (and change characteristics):\n        ```\n        \"vmname\" = {\n            name               = \"vmname\"\n            desc               = \"vmname - ubuntu 22.04 - {{ip_range}}.10\"\n            cores              = 4\n            memory             = 12000\n            clone              = \"Ubuntu2204_x64\"\n            dns                = \"{{ip_range}}.1\"\n            ip                 = \"{{ip_range}}.21/24\"\n            gateway            = \"{{ip_range}}.1\"\n        }\n        ```\n        - For a windows box (windows.tf file) (and change characteristics):\n        ```\n        \"vmname\" = {\n            name               = \"vmname\"\n            desc               = \"vmname - windows server 2019 - {{ip_range}}.10\"\n            cores              = 4\n            memory             = 12000\n            clone              = \"WinServer2019_x64\"\n            dns                = \"{{ip_range}}.1\"\n            ip                 = \"{{ip_range}}.21/24\"\n            gateway            = \"{{ip_range}}.1\"\n        }\n        ```\n\n    !!! warning\n        be sure to have the template ready to get clone (you should prepare it with packer first)\n\n=== \"🏟️  Ludus\"\n    - As an example to add a new box for ludus :\n        - Create the folder `extensions/<extension_name>/providers/ludus/`\n        - Add a file config.yml\n        - For a linux box (linux.tf file) (and change characteristics):\n        ```\n        - vm_name: \"{{ range_id }}-name\"\n            hostname: \"{{ range_id }}-name\"\n            template: ubuntu-22.04-x64-server-template\n            vlan: 10\n            ip_last_octet: 66\n            ram_gb: 8\n            cpus: 2\n            linux: true\n        ```\n        - For a windows box (windows.tf file) (and change characteristics):\n        ```\n        - vm_name: \"{{ range_id }}-name\"\n            hostname: \"{{ range_id }}-name\"\n            template: win2019-server-x64-template\n            vlan: 10\n            ip_last_octet: 66\n            ram_gb: 4\n            cpus: 4\n            windows:\n                sysprep: true\n        ```\n\n    !!! warning\n        be sure to have the template ready before see [https://docs.ludus.cloud/docs/templates](https://docs.ludus.cloud/docs/templates)\n\n## Ansible inventory\n- Create the ansible inventory file : `extension/<extension_name>/inventory`\n- an example could be :\n\n```ini\n[default]\nwazuh ansible_host={{ip_range}}.51 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no'\n\n[extensions]\nwazuh\n\n; Recipe associations -------------------\n[wazuh_server]\nwazuh\n\n[wazuh_agents:children]\ndomain\n```\n\nor for a windows machine associated to a domain:\n\n```ini\n[default]\n{% if provider_name == 'aws' or provider_name == 'azure' %}\nws01 ansible_host={{ip_range}}.31 dns_domain=dc01 dict_key=ws01 ansible_user=ansible ansible_password=EP+xh7Rk6j90\n{% else %}\nws01 ansible_host={{ip_range}}.31 dns_domain=dc01 dict_key=ws01\n{% endif %}\n\n[domain]\nws01\n\n[extensions]\nws01\n```\n\n- Domain contains all the windows vm associated with a domain. You can install something on all of them by using :\n\n```ini\n[inventory_group:children]\ndomain\n```\n\n- If you want to add your new vm to that group just add it and it will be merge with the main inventory:\n\n```ini\n[domain]\nvm_name\n```\n\n\n## Ansible tasks and roles\n\nThe providers to add the vms you need are setup, now you should add the provisioning part.\n\nTo do that you must add the file `extension/<extension_name>/ansible/install.yml`\n\nThe file should be the following:\n\n```yaml\n- name: task name\n  hosts: host_group_according_to_the_inventory\n  become: yes\n  roles:\n    - { role: '<role_name>', tags: '<tag_role_name>'}\n  vars:\n    role_variable: \"value\"\n```\n\nYou should create each ansible role you use in `extension/<extension_name>/ansible/roles/<role_name>`\n\n- If you need to use goad roles you can include it by creating an ansible.cfg file with the following contents:\n\n```ini\n# extension/<extension_name>/ansible/ansible.cfg\n[defaults]\nhost_key_checking = false\ndisplay_skipped_hosts = false\nshow_per_host_start     = True\ndeprecation_warning   = false\n;stdout_callback         = yaml\n\n; add default roles folder into roles_path\nroles_path = ./roles:../../../ansible/roles\n```\n\n- If you need the lab data for your extension add the following code on the start of the install.yml file:\n\n```yaml\n# read global configuration file and set up adapters\n- import_playbook: \"../../../ansible/data.yml\"\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n```\n\n- If you need to combine the lab data with your own json config file add to the install.yml :\n\n```yaml\n# read local configuration file\n- name: \"Read local config file\"\n  hosts: domain:extensions\n  connection: local\n  vars_files:\n    - \"../data/config.json\"\n  tasks:\n    - name: merge lab variable with local config\n      set_fact:\n        lab: \"{{ lab|combine(lab_extension, recursive=True) }}\"\n```\n\n- and create the json file in `extension/<extension_name>/data/config.json`\n\n```json\n{\n    \"lab_extension\": {\n        \"hosts\": {\n            ...\n        },\n        \"domains\": {\n            ...\n        }\n}\n```"
  },
  {
    "path": "docs/mkdocs/docs/developers/add_lab.md",
    "content": "# Add a new lab\n\n🚧 TODO TO BE COMPLETED\n\n- To create a new lab:\n    - Create a new folder in `ad/` with the name of the lab\n    - Create the following structure:\n    ```\n    ad/<lab_name>/\n        data/\n            config.json                 # json containing all the lab information\n            inventory                   # global lab inventory file with the vm groups and the main variables\n            inventory_disable_vagrant   # inventory to disable/enable vagrant\n        files/\n        providers/\n            aws|azure|proxmox/          # terraform based providers\n                inventory               # inventory specific to the provider\n                linux.tf                # linux vms\n                windows.tf              # windows vms\n            ludus/                      # ludus provider\n                inventory               # inventory specific to the provider\n                config.yml              # ludus configuration file\n            virtualbox|vmware/          # vagrant based provider\n                inventory               # inventory specific to the provider\n                Vagrantfile             # vms\n        scripts/\n    ```\n"
  },
  {
    "path": "docs/mkdocs/docs/developers/add_provider.md",
    "content": "# Add a new provider\n\n🚧 TODO TO BE COMPLETED\n\n## Provider files\n- Add the new provider files in each lab location : `ad/<lab>/providers/<provider_name>`\n- Add the new provider files in each extension location : `extensions/<extension>/providers/<provider_name>`\n- Create the provider templates file in : `template/provider/<provider_name>`\n\n## Provider python class\n- Create the new provider class in `goad/provider/`\n\n- If you use vagrant :\n    - create the new provider in `goad/provider/vagrant/myprovider.py`\n```python\nfrom goad.provider.vagrant.vagrant import VagrantProvider\nfrom goad.utils import *\n\n\nclass MyProviderProvider(VagrantProvider):\n    provider_name = MYPROVIDER\n    default_provisioner = PROVISIONING_LOCAL\n    # define the provisioner allowed\n    allowed_provisioners = [PROVISIONING_LOCAL, PROVISIONING_RUNNER, PROVISIONING_DOCKER, PROVISIONING_VM]\n\n    def check(self):\n        checks = [\n            super().check(),\n            self.command.check_myprovider(),\n            # self.command.check_vagrant_plugin('myvagrant_plugin', False)\n        ]\n        return all(checks)\n```\n\n    - add constants in `goad/utils.py`\n    ```python\n    MYPROVIDER = \"myprovider\"\n    ALLOWED_PROVIDERS = [AWS, VIRTUALBOX, AZURE, VMWARE, PROXMOX, LUDUS, MYPROVIDER]\n    ```\n\n    - add the check in the command class:\n    ```python\n    # goad/command/cmd.py\n    def check_myprovider(self):\n        pass\n    ```\n\n    - add the check in the inherited classes : linux.py/ windows.py / wsl.py\n    - add the new provider in the provider_factory.py file\n\n- If you use Terraform :\n    - create the new provider in `goad/provider/terraform/myprovider.py`\n```python\nfrom goad.provider.terraform.terraform import TerraformProvider\nfrom goad.utils import *\nfrom goad.log import Log\n\n\nclass MyProviderProvider(TerraformProvider):\n\n    provider_name = MYPROVIDER\n    default_provisioner = PROVISIONING_REMOTE\n    allowed_provisioners = [PROVISIONING_REMOTE]\n\n    def __init__(self, lab_name):\n        super().__init__(lab_name)\n        self.resource_group = lab_name\n        self.jumpbox_setup_script = 'setup_script.sh'\n\n    def check(self):\n        check = super().check()\n        myproviders_checks = [\n            self.command.mycheck()\n        ]\n        return check and all(myproviders_checks)\n\n    def start(self):\n        # TODO\n        pass\n\n    def stop(self):\n        # TODO\n        pass\n\n    def status(self):\n        # TODO\n        pass\n\n    def start_vm(self, vm_name):\n        # TODO\n        pass\n\n    def stop_vm(self, vm_name):\n        # TODO\n        pass\n\n    def destroy_vm(self, vm_name):\n        # TODO\n        pass\n\n    def ssh_jumpbox(self):\n        # TODO\n        pass\n\n    def get_jumpbox_ip(self, ip_range=''):\n        # TODO\n        pass\n```\n\n    - add constants in `goad/utils.py`\n    - add the check commands in the cmd.py and the inherited classes : linux.py/ windows.py / wsl.py\n    - add the new provider in the provider_factory.py file\n\n\n- next adapt the menu if needed in menu.py\n- add dependencies if needed in the requirements files, in the dependencies.py files and in the config.py files\n- add a provider color if you want in instances.py\n- define if is_terraform or is_vagrant in instance.py\n"
  },
  {
    "path": "docs/mkdocs/docs/developers/index.md",
    "content": "# Developers guide"
  },
  {
    "path": "docs/mkdocs/docs/extensions/elk.md",
    "content": "# elk\n\n- Extension name : `elk`\n- Compatibility  : `*`\n- Providers : virtualbox/azure/vmware/aws/ludus\n- Add a machine  : elk  (ip_range.50)\n\n- Kibana is configured on http://{{ip_range}}.50:5601 to follow the lab events\n- Infos : log encyclopedia : https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/\n- Install filebeat agent on domain computer machines\n\n## prerequisites\n\n- You need `sshpass` for the elk installation\n```bash\nsudo apt install sshpass\n```\n\n- On ludus prepare template :\n```\nludus templates add -d ubuntu-22.04-x64-server\nludus templates build\n```\n\n## Install\n\n- select your instance\n```\nload <instance_id>\n```\n\n- install the elk extension\n```\ninstall_extension elk\n```\n\n\n"
  },
  {
    "path": "docs/mkdocs/docs/extensions/exchange.md",
    "content": "# exchange\n\n!!! success \"Thanks!\"\n    Credits and huge thanks to [aleemladha](https://github.com/aleemladha) for his exchange role and his help to test the extension.\n\n- Extension name : `exchange`\n- Compatibility  : GOAD, GOAD-Light\n- Providers : virtualbox/azure/vmware/aws/ludus/proxmox\n- Add a machine  : srv01 (the-eyrie.sevenkingdoms.local)  (ip_range.21)\n\n!!! warning \"resources\"\n    Exchange is really HUGE, it will add a vm with at least 12Gb of RAM be sure your computer support it before install\n\n!!! warning \"impacts\"\n    Modify the ad schema and add a computer (warning the exchange machine is really heavy)\n\n## Prerequisites\n\n- GOAD or GOAD-Light installation\n\n## Installation\n\n- select your instance\n```\nload <instance_id>\n```\n\n- install the exchange extension\n```\ninstall_extension exchange\n```\n"
  },
  {
    "path": "docs/mkdocs/docs/extensions/guacamole.md",
    "content": "# guacamole\n\n- Extension name : `guacamole`\n- Description : Add a linux ubuntu 22.4 with guacamole ()\n- Compatibility  : any\n- Providers : virtualbox/azure/vmware/aws/ludus\n\n- Add a machine  : {{lab_name}}-GUACAMOLE (ip_range.52)\n\n## Info\n\nConnect to http://(ip_range).52:8080/guacamole\n\nAnd enjoy quick access to your lab :)\n\n![guacamole_screen.png](../img/guacamole_screen.png)\n\n\n## Prerequisites\n\n- Edit the file `/guacamole.yml` to change password to use and define users\n\n- On ludus prepare template :\n```\nludus templates add -d ubuntu-22.04-x64-server\nludus templates build\n```\n\n- If you get an ansible error on provisioning saying \"missing role...\" maybe you need to relaunch ansible-galaxy requirements install first\n```bash\nsource ~/.goad/.venv/activate\ncd ansible\n# python <3.11\nansible-galaxy install -r requirements.yml\n# python => 3.11\nansible-galaxy install -r requirements_311.yml\n```\n\n## Installation\n\n- select your instance\n```\nload <instance_id>\n```\n\n- install the guacamole extension\n```\ninstall_extension guacamole\n```\n\n- if something goes wrong and you just need to relaunch the provision to add new users\n```\nprovision_extension guacamole\n```\n"
  },
  {
    "path": "docs/mkdocs/docs/extensions/index.md",
    "content": "# Extensions\n\n- [guacamole](guacamole.md) : Add a vm with guacamole to get a quick access on lab\n- [exchange](exchange.md) : Add an exchange to GOAD or GOAD-Light lab\n- [ws01](ws01.md) : Add an hardened workstation to GOAD or GOAD-Light lab\n- [lx01](lx01.md) : Add a linux vm to GOAD or GOAD-Light lab\n- [wazuh](wazuh.md) : Add wazuh EDR to visualize alerts\n- [elk](elk.md) : Add an ELK to collect and read the logs\n"
  },
  {
    "path": "docs/mkdocs/docs/extensions/lx01.md",
    "content": "# lx01\n\n- Extension name : `lx01`\n- Description : Add a linux ubuntu 22.4 to the lab GOAD or GOAD Light in the domain sevenkingdoms.local\n- Compatibility  : GOAD / GOAD-Light /Goad-Mini \n- Providers : virtualbox/azure/vmware/aws/ludus\n\n- Add a machine  : {{lab_name}}-LX01 (dragonstone.sevenkingdoms.local)  (ip_range.32)\n\n## Lab info\n- Lab infos:\n    - hostname: dragonstone \n    - Users:\n        - Sudoers :\n            - Baratheon group\n        - SSH Users:\n            - Lannister group\n            - Baratheon group\n\n- Features :\n    - just an AD enrolled linux machine\n\n## Prerequisites\n\n- GOAD or GOAD-Light installation\n\n- On ludus prepare template :\n```\nludus templates add -d ubuntu-22.04-x64-server\nludus templates build\n```\n\n## Installation\n\n- select your instance\n```\nload <instance_id>\n```\n\n- install the lx01 extension\n```\ninstall_extension lx01\n```\n\n- if something goes wrong and you just need to relaunch the provision\n```\nprovision_extension lx01\n```\n"
  },
  {
    "path": "docs/mkdocs/docs/extensions/wazuh.md",
    "content": "# wazuh\n\n!!! success \"Thanks!\"\n    Credits and huge thanks to [aleemladha](https://github.com/aleemladha) for the ansible role. [https://github.com/Orange-Cyberdefense/GOAD/pull/215](https://github.com/Orange-Cyberdefense/GOAD/pull/215)\n\n- Extension name : `wazuh`\n- Description : Add wazuh free EDR server and agent on all the domain computers + soc fortress rules (https://github.com/socfortress/Wazuh-Rules)\n- Compatibility  : *\n- Providers : virtualbox/azure/vmware/aws/ludus \n- Add a machine  : wazuh (ip_range.51)\n\n!!! warning \"impacts\"\n    add a wazuh machine and a wazuh agent on all windows machine\"\n\n\n## Prerequisites\n\n- On ludus prepare template :\n```\nludus templates add -d ubuntu-22.04-x64-server\nludus templates build\n```\n\n- A lab installed\n\n## Installation\n\n- select your instance\n```\nload <instance_id>\n```\n\n- install the exchange extension\n```\ninstall_extension wazuh\n```\n"
  },
  {
    "path": "docs/mkdocs/docs/extensions/ws01.md",
    "content": "# ws01\n\n- Extension name : `ws01`\n- Description : Add a Windows 10 workstation to the lab GOAD or GOAD Light in the domain sevenkingdoms.local\n- Compatibility  : GOAD / GOAD-Light /Goad-Mini \n- Providers : virtualbox/azure/vmware/aws/ludus/proxmox\n\n- Add a machine  : {{lab_name}}-WS01 (casterlyrock.sevenkingdoms.local)  (ip_range.31)\n\n!!! warning \"rearm\"\n    The vm is not armed by default (90 days trials), connect to the vm with vagrant/vagrant and run as admin `slmgr -rearm` to rearm the box. (need a restart)\n\n!!! warning \"aws\"\n    AWS doesn't got any windows 10 so for aws the vm is a windows server 2019\n\n## Lab info\n- Lab infos:\n    - hostname: casterlyrock \n    - Users:\n        - Administrators :\n            - tywin.lannister\n            - jaime.lannister\n        - RDP Users:\n            - Lannister group\n\n- Features :\n    - run_as_ppl\n    - powershell restricted\n    - asr rules :\n        - block lsass stealing\n        - block PSExec and WMI\n\n## Prerequisites\n\n- GOAD or GOAD-Light installation\n\n- On ludus prepare template :\n```\nludus templates add -d win10-21h1-x64-enterprise\nludus templates build\n```\n\n## Installation\n\n- select your instance\n```\nload <instance_id>\n```\n\n- install the ws01 extension\n```\ninstall_extension ws01\n```\n\n## thanks\n\n- asr rules implementation : https://github.com/zuesdevil (https://github.com/Orange-Cyberdefense/GOAD/pull/172)"
  },
  {
    "path": "docs/mkdocs/docs/img/azure_architecture.excalidraw",
    "content": "{\n  \"type\": \"excalidraw\",\n  \"version\": 2,\n  \"source\": \"https://excalidraw.com\",\n  \"elements\": [\n    {\n      \"type\": \"ellipse\",\n      \"version\": 1190,\n      \"versionNonce\": 879623545,\n      \"isDeleted\": false,\n      \"id\": \"uplFgC4-Dk3AkhEnhzuf-\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 536.2073479545918,\n      \"y\": 327.76945353274573,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 96.53424794765822,\n      \"height\": 92.54522943742442,\n      \"seed\": 142161433,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"cMIoGo9YKI2HKyZ8oisu_\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 877,\n      \"versionNonce\": 261452439,\n      \"isDeleted\": false,\n      \"id\": \"vFgxYfpNuQWo0OgJWKPKQ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 585.7083172551709,\n      \"y\": 330.0929691802562,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 1.5956074040935242,\n      \"height\": 90.15181833128413,\n      \"seed\": 1610418937,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -1.5956074040935242,\n          90.15181833128413\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 892,\n      \"versionNonce\": 1956767321,\n      \"isDeleted\": false,\n      \"id\": \"uovg_10TscLf96o6_yAGA\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 554.3334108187364,\n      \"y\": 342.93186601277887,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 71.00452948216183,\n      \"height\": 16.753877742982,\n      \"seed\": 1173570521,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -1.595607404093524,\n          -0.797803702046762\n        ],\n        [\n          -1.595607404093524,\n          -1.5956074040935238\n        ],\n        [\n          1.5956074040935238,\n          2.393411106140286\n        ],\n        [\n          11.96705553070143,\n          9.57364442456114\n        ],\n        [\n          42.283596208478386,\n          15.158270338888476\n        ],\n        [\n          45.47481101666544,\n          13.56266293479494\n        ],\n        [\n          58.23967024941363,\n          10.371448126607909\n        ],\n        [\n          68.61111837602157,\n          2.393411106140286\n        ],\n        [\n          68.61111837602157,\n          0.797803702046762\n        ],\n        [\n          69.4089220780683,\n          0.797803702046762\n        ],\n        [\n          68.61111837602157,\n          3.1912148081870484\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 882,\n      \"versionNonce\": 194578359,\n      \"isDeleted\": false,\n      \"id\": \"5mX_8OE34_d8eN6Nr7ucJ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 551.3379040475968,\n      \"y\": 410.70659403230053,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 70.2067257801151,\n      \"height\": 18.349485147075526,\n      \"seed\": 107962553,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          13.562662934794957,\n          -9.573644424561149\n        ],\n        [\n          47.07041842075897,\n          -18.349485147075526\n        ],\n        [\n          57.4418665473669,\n          -16.753877742982002\n        ],\n        [\n          67.015510971928,\n          -7.978037020467623\n        ],\n        [\n          68.61111837602155,\n          -4.786822212280571\n        ],\n        [\n          70.2067257801151,\n          -3.989018510233811\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 875,\n      \"versionNonce\": 1545974585,\n      \"isDeleted\": false,\n      \"id\": \"Kva-tLNzKOz51EnpQZnhE\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 536.1346926202987,\n      \"y\": 376.21983373856875,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 94.14083684151794,\n      \"height\": 0.7978037020467621,\n      \"seed\": 521462169,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          94.14083684151794,\n          0.7978037020467621\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 887,\n      \"versionNonce\": 682424535,\n      \"isDeleted\": false,\n      \"id\": \"I0cDOu8M0fGL2OpsNIocx\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 584.8397496811956,\n      \"y\": 332.338595830696,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 23.934111061402866,\n      \"height\": 90.94962203333087,\n      \"seed\": 219629177,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          2.3934111061402867,\n          -0.7978037020467623\n        ],\n        [\n          6.382429616374097,\n          0\n        ],\n        [\n          16.753877742982,\n          7.978037020467621\n        ],\n        [\n          18.349485147075526,\n          10.371448126607909\n        ],\n        [\n          23.934111061402866,\n          38.29457769824459\n        ],\n        [\n          23.934111061402866,\n          51.05943693099279\n        ],\n        [\n          19.147288849122294,\n          67.01551097192802\n        ],\n        [\n          11.169251828654675,\n          82.17378131081651\n        ],\n        [\n          3.9890185102338105,\n          90.1518183312841\n        ],\n        [\n          1.5956074040935242,\n          89.35401462923738\n        ],\n        [\n          1.5956074040935242,\n          90.1518183312841\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 883,\n      \"versionNonce\": 1063052313,\n      \"isDeleted\": false,\n      \"id\": \"6gWtAFcMSqKWTk-KP3rz5\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 583.9009247044912,\n      \"y\": 334.0533564519932,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"transparent\",\n      \"width\": 27.92312957163668,\n      \"height\": 83.76938871491002,\n      \"seed\": 1530531673,\n      \"groupIds\": [\n        \"bLerI3XUpci7lK3cEfs7s\",\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -0.7978037020467624,\n          -1.5956074040935246\n        ],\n        [\n          -14.360466636841723,\n          8.775840722514387\n        ],\n        [\n          -23.934111061402863,\n          24.731914763449627\n        ],\n        [\n          -27.92312957163668,\n          47.868222122805726\n        ],\n        [\n          -24.73191476344963,\n          63.02649246169427\n        ],\n        [\n          -20.742896253215818,\n          70.20672578011508\n        ],\n        [\n          -17.551681445028773,\n          71.00452948216189\n        ],\n        [\n          -11.169251828654671,\n          75.79135169444241\n        ],\n        [\n          -7.18023331842086,\n          82.1737813108165\n        ],\n        [\n          -3.989018510233811,\n          82.1737813108165\n        ]\n      ]\n    },\n    {\n      \"id\": \"CXbgcj4C2cvKYtAEM9oj9\",\n      \"type\": \"text\",\n      \"x\": 641.8406731058137,\n      \"y\": 359.74953599139485,\n      \"width\": 82.65992736816406,\n      \"height\": 25,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"transparent\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"Hn9MbZd8Mk4R92T0aKGkU\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 991192249,\n      \"version\": 406,\n      \"versionNonce\": 476431863,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"Internet\",\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 18,\n      \"containerId\": null,\n      \"originalText\": \"Internet\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"id\": \"tgYncXat4V-ZZ6dAX7H1M\",\n      \"type\": \"rectangle\",\n      \"x\": 825,\n      \"y\": 65.66666666666674,\n      \"width\": 1039,\n      \"height\": 672.3333333333334,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"transparent\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"seed\": 1949355385,\n      \"version\": 86,\n      \"versionNonce\": 440072441,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"id\": \"AwhPnr7jU-dMecvIaN0uh\",\n      \"type\": \"text\",\n      \"x\": 912.3333333333333,\n      \"y\": 101.33333333333326,\n      \"width\": 117.41987609863281,\n      \"height\": 25,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"transparent\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"u2P_98sWb5Bhs5WpsKqzX\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 306581529,\n      \"version\": 42,\n      \"versionNonce\": 1297555191,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"Azure Cloud\",\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 18,\n      \"containerId\": null,\n      \"originalText\": \"Azure Cloud\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1065,\n      \"versionNonce\": 778547193,\n      \"isDeleted\": false,\n      \"id\": \"822jLVnQzcpmF5a9dXVNI\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 871.0299142994818,\n      \"y\": 100.02679836146,\n      \"strokeColor\": \"#364fc7\",\n      \"backgroundColor\": \"#364fc7\",\n      \"width\": 34.602985560653366,\n      \"height\": 46.08332597580886,\n      \"seed\": 1808334999,\n      \"groupIds\": [\n        \"UZy6hKatbQTMO105II0jD\",\n        \"u2P_98sWb5Bhs5WpsKqzX\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -23.802008451178224,\n          38.612875109738454\n        ],\n        [\n          -9.241920562053707,\n          39.14703774162111\n        ],\n        [\n          10.800977109475136,\n          -6.936288234187749\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1138,\n      \"versionNonce\": 287713303,\n      \"isDeleted\": false,\n      \"id\": \"oy7qYkLiG_n1PGGebhpF4\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 884.7935521793275,\n      \"y\": 89.01839762974379,\n      \"strokeColor\": \"#364fc7\",\n      \"backgroundColor\": \"#364fc7\",\n      \"width\": 43.93680928103998,\n      \"height\": 44.77892013157281,\n      \"seed\": 1982518711,\n      \"groupIds\": [\n        \"UZy6hKatbQTMO105II0jD\",\n        \"u2P_98sWb5Bhs5WpsKqzX\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -4.998495928910919,\n          11.442322194536532\n        ],\n        [\n          14.172843983209026,\n          38.21963697033442\n        ],\n        [\n          -19.154235186843934,\n          44.608403453747805\n        ],\n        [\n          24.782574094196043,\n          44.77892013157281\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"id\": \"x22xWojHWMJuGKn0WqHFW\",\n      \"type\": \"rectangle\",\n      \"x\": 987.9724005808569,\n      \"y\": 160.0773848420983,\n      \"width\": 827.1403326680916,\n      \"height\": 504.28580527481137,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"sh8LougDhYvcHPpOZxfhb\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"seed\": 53679575,\n      \"version\": 1172,\n      \"versionNonce\": 1387588311,\n      \"isDeleted\": false,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"id\": \"XFdEwGB-Wu5mcUaa43gOM\",\n      \"type\": \"text\",\n      \"x\": 1627.4479489807643,\n      \"y\": 186.34455600640382,\n      \"width\": 161.89770889431975,\n      \"height\": 25.655717514518976,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"sh8LougDhYvcHPpOZxfhb\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 343127385,\n      \"version\": 835,\n      \"versionNonce\": 260379161,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"192.168.56.0/24\",\n      \"fontSize\": 20.52457401161518,\n      \"fontFamily\": 1,\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 17,\n      \"containerId\": null,\n      \"originalText\": \"192.168.56.0/24\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1920,\n      \"versionNonce\": 1688172535,\n      \"isDeleted\": false,\n      \"id\": \"XtLMpQckYEMcpPvaOAINJ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 4,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1036.9878536966476,\n      \"y\": 175.77801756229388,\n      \"strokeColor\": \"#1864ab\",\n      \"backgroundColor\": \"#66cce6\",\n      \"width\": 25.28470724739857,\n      \"height\": 44.26282148404956,\n      \"seed\": 1593209689,\n      \"groupIds\": [\n        \"sWM2do492m2OlX37eT7Fl\",\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -25.28470724739857,\n          22.735422651414982\n        ],\n        [\n          -2.00838706310297,\n          44.26282148404956\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 2152,\n      \"versionNonce\": 1361929977,\n      \"isDeleted\": false,\n      \"id\": \"0CU9IwircF79r5_kKcKUq\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 4,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1047.9404335765153,\n      \"y\": 175.03260388578474,\n      \"strokeColor\": \"#1864ab\",\n      \"backgroundColor\": \"#66cce6\",\n      \"width\": 25.304369328744436,\n      \"height\": 44.26282148404956,\n      \"seed\": 106995769,\n      \"groupIds\": [\n        \"sWM2do492m2OlX37eT7Fl\",\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          25.304369328744436,\n          22.735422651414982\n        ],\n        [\n          2.0099488399280823,\n          44.26282148404956\n        ]\n      ]\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 1860,\n      \"versionNonce\": 805003543,\n      \"isDeleted\": false,\n      \"id\": \"hvtWFYMQTyYr7TOxQNLpS\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1025.7692007895155,\n      \"y\": 193.34882305035586,\n      \"strokeColor\": \"#495057\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 7.151150347507662,\n      \"height\": 7.151150347507662,\n      \"seed\": 498217241,\n      \"groupIds\": [\n        \"sWM2do492m2OlX37eT7Fl\",\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 1905,\n      \"versionNonce\": 1756897241,\n      \"isDeleted\": false,\n      \"id\": \"74qdPU0xdiRFxKrBuff83\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1038.231635574137,\n      \"y\": 193.5160784862519,\n      \"strokeColor\": \"#495057\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 7.151150347507662,\n      \"height\": 7.151150347507662,\n      \"seed\": 2053023225,\n      \"groupIds\": [\n        \"sWM2do492m2OlX37eT7Fl\",\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 1954,\n      \"versionNonce\": 909977143,\n      \"isDeleted\": false,\n      \"id\": \"BQRIATj4gqDlvCm1EROCF\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1051.7149239657892,\n      \"y\": 193.4146964401125,\n      \"strokeColor\": \"#495057\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 7.151150347507662,\n      \"height\": 7.151150347507662,\n      \"seed\": 2003402457,\n      \"groupIds\": [\n        \"sWM2do492m2OlX37eT7Fl\",\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 1857,\n      \"versionNonce\": 876133561,\n      \"isDeleted\": false,\n      \"id\": \"Wl7AXyTyNMk3b3OYg8qLL\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1005.166460451312,\n      \"y\": 225.39776470481524,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#364fc7\",\n      \"width\": 76.49380878402103,\n      \"height\": 49.03449281026989,\n      \"seed\": 1130773433,\n      \"groupIds\": [\n        \"kKKrZgQtZpEC56L47WkQC\",\n        \"Zj19zs3SLH-3MWIP4_5wM\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 19.61379712410795,\n      \"fontFamily\": 1,\n      \"text\": \"Virtual\\nNetwork\",\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Virtual\\nNetwork\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 42.000000000000014\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1058,\n      \"versionNonce\": 1447642967,\n      \"isDeleted\": false,\n      \"id\": \"6UMPol5zLg6IVit-YoCbF\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1197.5392994862877,\n      \"y\": 314.16472642668555,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#868e96\",\n      \"width\": 41.63900243351605,\n      \"height\": 11.96910596267062,\n      \"seed\": 169682423,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          19.218001123161184,\n          -6.068842459945697\n        ],\n        [\n          12.306263877112068,\n          -11.29479013378779\n        ],\n        [\n          31.35568604305254,\n          -11.126211176567086\n        ],\n        [\n          23.263896096458378,\n          -5.900263502724988\n        ],\n        [\n          41.63900243351605,\n          -1.5172106149864244\n        ],\n        [\n          2.69726331553143,\n          0.6743158288828293\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1075,\n      \"versionNonce\": 55754137,\n      \"isDeleted\": false,\n      \"id\": \"4gKuiSVzgU5zXQPVrsm4M\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1182.4729818454052,\n      \"y\": 240.6242747832859,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 71.98321473324478,\n      \"height\": 62.728229981827305,\n      \"seed\": 1972588311,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 897,\n      \"versionNonce\": 510936183,\n      \"isDeleted\": false,\n      \"id\": \"B_3Giz805Ui3Ky1mz4ldg\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1191.8948462501974,\n      \"y\": 252.20108565529597,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#59b6da\",\n      \"width\": 55.44048836597695,\n      \"height\": 40.9097152055396,\n      \"seed\": 514282551,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 872,\n      \"versionNonce\": 1698275961,\n      \"isDeleted\": false,\n      \"id\": \"Y8Shrj73uK17JWh6rvtiI\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1219.6371694807258,\n      \"y\": 245.35382103781382,\n      \"strokeColor\": \"#82c91e\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 3.173863083476339,\n      \"height\": 2.2851814201029743,\n      \"seed\": 1295889751,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 900,\n      \"versionNonce\": 1585618327,\n      \"isDeleted\": false,\n      \"id\": \"nWKxNY86ASSntM1gnPWHj\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1197.416229269838,\n      \"y\": 312.7175736866611,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 41.80758139073692,\n      \"height\": 8.091789946594178,\n      \"seed\": 1487598199,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1416,\n      \"versionNonce\": 917564249,\n      \"isDeleted\": false,\n      \"id\": \"TVL2vn8Yijth6vtyAmIrl\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1219.9387114579283,\n      \"y\": 273.08749064030775,\n      \"strokeColor\": \"#99d2ea\",\n      \"backgroundColor\": \"#99d2ea\",\n      \"width\": 9.62325599292749,\n      \"height\": 19.129117180901776,\n      \"seed\": 968067991,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          9.095150481120506,\n          -7.1891846987564945\n        ],\n        [\n          9.62325599292749,\n          5.549546083250626\n        ],\n        [\n          0.6454622922085516,\n          11.939932482145283\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1210,\n      \"versionNonce\": 2041107127,\n      \"isDeleted\": false,\n      \"id\": \"beawX6OIKL_toHg4NfHP9\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1219.0172252136695,\n      \"y\": 269.57969229048695,\n      \"strokeColor\": \"#000\",\n      \"backgroundColor\": \"#000000\",\n      \"width\": 17.000696729698905,\n      \"height\": 13.945897371768192,\n      \"seed\": 1552679095,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          7.610420196688328,\n          -7.544268539716403\n        ],\n        [\n          2.6455684080248534,\n          -13.945897371768192\n        ],\n        [\n          -9.390276533010576,\n          -5.337441687962625\n        ],\n        [\n          -0.1841230692746738,\n          -0.9237879844550655\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1209,\n      \"versionNonce\": 1879840825,\n      \"isDeleted\": false,\n      \"id\": \"cNDO0djNdSRovGgKplKQs\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1207.8236917386369,\n      \"y\": 265.88993440521824,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 8.923969558630365,\n      \"height\": 18.152647395677405,\n      \"seed\": 853070295,\n      \"groupIds\": [\n        \"tkIBhcOIggs8pD9SUUVBK\",\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.48054249981645,\n          6.2000239344391055\n        ],\n        [\n          8.923969558630365,\n          18.152647395677405\n        ],\n        [\n          1.7182798529039773,\n          12.847472276518157\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 724,\n      \"versionNonce\": 2022400983,\n      \"isDeleted\": false,\n      \"id\": \"FLuHTL7vlxV7h0XCrkNXu\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1154.0423222095924,\n      \"y\": 330.3863532045007,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 124.7317331446735,\n      \"height\": 49.44168574184478,\n      \"seed\": 95321847,\n      \"groupIds\": [\n        \"pKyr5O4dKtM0YdHFJG7xQ\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"SAhg2CJFAfFnLulnaYOt8\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 19.776674296737912,\n      \"fontFamily\": 1,\n      \"text\": \"DC01\\n192.168.56.10\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"DC01\\n192.168.56.10\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 42\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1105,\n      \"versionNonce\": 858695961,\n      \"isDeleted\": false,\n      \"id\": \"2my-5pBCON_yAwxnie5DJ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1395.6512835042092,\n      \"y\": 315.35275336429584,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#868e96\",\n      \"width\": 42.11414526485284,\n      \"height\": 12.105685480990102,\n      \"seed\": 222624087,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          19.437297814547392,\n          -6.138094046699237\n        ],\n        [\n          12.446690705806747,\n          -11.423675031356881\n        ],\n        [\n          31.71348590794583,\n          -11.253172418948576\n        ],\n        [\n          23.52936051234695,\n          -5.96759143429093\n        ],\n        [\n          42.11414526485284,\n          -1.5345235116748095\n        ],\n        [\n          2.7280417985330034,\n          0.6820104496332223\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1122,\n      \"versionNonce\": 1530843383,\n      \"isDeleted\": false,\n      \"id\": \"DFR-zvglw6IOPw2Q6hmG3\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1380.4130440495621,\n      \"y\": 240.9731313188813,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 72.80461549834928,\n      \"height\": 63.444022077132644,\n      \"seed\": 522827383,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 944,\n      \"versionNonce\": 428613113,\n      \"isDeleted\": false,\n      \"id\": \"UVJ8QjuF3HWobQSAG-Ozx\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1389.9424213885782,\n      \"y\": 252.68204522828682,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#59b6da\",\n      \"width\": 56.07312001115059,\n      \"height\": 41.37653613726047,\n      \"seed\": 1270468503,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 919,\n      \"versionNonce\": 726112791,\n      \"isDeleted\": false,\n      \"id\": \"odwKmZ8kANyEnuV6zzU_1\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1418.0013123857973,\n      \"y\": 245.75664644554797,\n      \"strokeColor\": \"#82c91e\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 3.210080048428036,\n      \"height\": 2.3112576348681957,\n      \"seed\": 1563018423,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 947,\n      \"versionNonce\": 1109915353,\n      \"isDeleted\": false,\n      \"id\": \"KWhh-fEJ8T0pQvlnTDDio\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1395.5268089330036,\n      \"y\": 313.8890871582879,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 42.28464787726131,\n      \"height\": 8.184125395598898,\n      \"seed\": 1662916055,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1463,\n      \"versionNonce\": 1301954359,\n      \"isDeleted\": false,\n      \"id\": \"WB4lpuWkVZLwFHecsEX-S\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1418.3062952597659,\n      \"y\": 273.80678506814695,\n      \"strokeColor\": \"#99d2ea\",\n      \"backgroundColor\": \"#99d2ea\",\n      \"width\": 9.73306700740746,\n      \"height\": 19.347399617250225,\n      \"seed\": 78332663,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          9.198935281391208,\n          -7.2712205154940435\n        ],\n        [\n          9.73306700740746,\n          5.612871976872594\n        ],\n        [\n          0.6528276651309886,\n          12.076179101756182\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1253,\n      \"versionNonce\": 529904569,\n      \"isDeleted\": false,\n      \"id\": \"StkSV3WaCj9GwIERrtudM\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1417.3742939321105,\n      \"y\": 270.2589592166503,\n      \"strokeColor\": \"#000\",\n      \"backgroundColor\": \"#000000\",\n      \"width\": 17.19469175135546,\n      \"height\": 10.277622663204461,\n      \"seed\": 307612695,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          7.697262733458771,\n          -7.630356219651804\n        ],\n        [\n          0.12414939892676406,\n          -10.277622663204461\n        ],\n        [\n          -9.497429017896687,\n          -5.398347257440731\n        ],\n        [\n          -0.18622409839008727,\n          -0.9343293330185839\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1229,\n      \"versionNonce\": 345718871,\n      \"isDeleted\": false,\n      \"id\": \"sLXF7F-uP5QkLH76ptug0\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1406.053030999666,\n      \"y\": 266.5270974886836,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 9.02580101267687,\n      \"height\": 18.359787331212893,\n      \"seed\": 1477587255,\n      \"groupIds\": [\n        \"zVg2o86d2yChbSmaGXcS2\",\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.5773140058358,\n          6.270772433548056\n        ],\n        [\n          9.02580101267687,\n          18.359787331212893\n        ],\n        [\n          1.7378871515092051,\n          12.994074836527426\n        ],\n        [\n          0.9530348895373422,\n          2.2626498471565153\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 774,\n      \"versionNonce\": 100193433,\n      \"isDeleted\": false,\n      \"id\": \"rWHSJYGi-z3aEn2JRzgPA\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1354.585534638246,\n      \"y\": 331.75948519328057,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 117.81405377513887,\n      \"height\": 50.00586502512499,\n      \"seed\": 793047639,\n      \"groupIds\": [\n        \"yNprDUnSlzpcG6knw4nW2\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"l8S7i1jyyXiaBDgV1tqr5\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 20.002346010049994,\n      \"fontFamily\": 1,\n      \"text\": \"DC02\\n192.168.56.11\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"DC02\\n192.168.56.11\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 43.00000000000001\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1146,\n      \"versionNonce\": 304029047,\n      \"isDeleted\": false,\n      \"id\": \"diGpIyZjjBogumvka-3ei\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1602.9069886300722,\n      \"y\": 312.904310821427,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#868e96\",\n      \"width\": 39.502252566143426,\n      \"height\": 11.354898510915737,\n      \"seed\": 1092554393,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          18.231808876681516,\n          -5.75741332947843\n        ],\n        [\n          11.67475480699789,\n          -10.71518591875149\n        ],\n        [\n          29.74663553563834,\n          -10.555257770710432\n        ],\n        [\n          22.070084429667197,\n          -5.597485181437367\n        ],\n        [\n          39.502252566143426,\n          -1.4393533323696077\n        ],\n        [\n          2.5588503686570885,\n          0.6397125921642455\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1163,\n      \"versionNonce\": 2030360953,\n      \"isDeleted\": false,\n      \"id\": \"QPYi7kXiMbyDrW4ST8ogZ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1588.6138151650698,\n      \"y\": 243.13766597242528,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 68.28931921353582,\n      \"height\": 59.50926388608093,\n      \"seed\": 659805049,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 985,\n      \"versionNonce\": 694834839,\n      \"isDeleted\": false,\n      \"id\": \"K_SB_hJvujifkLvTqp2RJ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1597.5521865383114,\n      \"y\": 254.12040043410678,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#59b6da\",\n      \"width\": 52.595500512288076,\n      \"height\": 38.8103894909224,\n      \"seed\": 2019359833,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 960,\n      \"versionNonce\": 972898905,\n      \"isDeleted\": false,\n      \"id\": \"ZJEhMOKlQOxtMALnKl9ZT\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1623.870882832097,\n      \"y\": 247.62451051121863,\n      \"strokeColor\": \"#82c91e\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 3.010992910649668,\n      \"height\": 2.1679148956677707,\n      \"seed\": 604899641,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 988,\n      \"versionNonce\": 1630628791,\n      \"isDeleted\": false,\n      \"id\": \"Rlq3Nm03rE9HpPxkIJPSG\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1602.7902338931801,\n      \"y\": 311.53142026936575,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 39.66218071418464,\n      \"height\": 7.67655110597116,\n      \"seed\": 1405778457,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1504,\n      \"versionNonce\": 364220217,\n      \"isDeleted\": false,\n      \"id\": \"gOhWw8t-9pepRu-AGBNdZ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1624.1569508607863,\n      \"y\": 273.9349972471319,\n      \"strokeColor\": \"#99d2ea\",\n      \"backgroundColor\": \"#99d2ea\",\n      \"width\": 9.129428337007726,\n      \"height\": 18.14748610881954,\n      \"seed\": 948293369,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.628423123391459,\n          -6.820264010127786\n        ],\n        [\n          9.129428337007726,\n          5.264765200800395\n        ],\n        [\n          0.6123397055310065,\n          11.327222098691754\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1325,\n      \"versionNonce\": 1972952279,\n      \"isDeleted\": false,\n      \"id\": \"h3JNkkwWuhhqlxKLXOnBH\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1623.2827516670122,\n      \"y\": 270.60720531486936,\n      \"strokeColor\": \"#000\",\n      \"backgroundColor\": \"#000000\",\n      \"width\": 16.128287825560832,\n      \"height\": 9.640210994861349,\n      \"seed\": 415467481,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          7.219883358734822,\n          -7.157126344669795\n        ],\n        [\n          0.11644973159250623,\n          -9.640210994861349\n        ],\n        [\n          -8.90840446682601,\n          -5.063545169018085\n        ],\n        [\n          -0.17467459738870414,\n          -0.8763828177146646\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1270,\n      \"versionNonce\": 1922121753,\n      \"isDeleted\": false,\n      \"id\": \"E2NC8whZC2YJ_Dclf9IiY\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1612.6636263134612,\n      \"y\": 267.1067912949962,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 8.466026532706854,\n      \"height\": 17.221124913189815,\n      \"seed\": 513221817,\n      \"groupIds\": [\n        \"72THVXPud8FOdgQNpFdo0\",\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358772,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.045354406858081,\n          5.881863086547217\n        ],\n        [\n          8.466026532706854,\n          17.221124913189815\n        ],\n        [\n          1.6301044876640471,\n          12.188190519546305\n        ],\n        [\n          0.8939282674287049,\n          2.122321732259305\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 822,\n      \"versionNonce\": 708127223,\n      \"isDeleted\": false,\n      \"id\": \"yN10xzW1r35OxRKCg_xMP\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1560.251122979581,\n      \"y\": 328.2935075014892,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 118.78127774814433,\n      \"height\": 46.90453284966765,\n      \"seed\": 1705256345,\n      \"groupIds\": [\n        \"-Uh4VlfuTDS10aurxpGWx\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"5EnmiI-P42lyF3ONrbFTZ\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 18.76181313986706,\n      \"fontFamily\": 1,\n      \"text\": \"DC03\\n192.168.56.12\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"DC03\\n192.168.56.12\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 39.00000000000001\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1164,\n      \"versionNonce\": 511956217,\n      \"isDeleted\": false,\n      \"id\": \"l98Ot9PekroOdjP9lEmQy\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1277.667903583145,\n      \"y\": 558.8891049254931,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#868e96\",\n      \"width\": 40.19126481904397,\n      \"height\": 11.552954664583504,\n      \"seed\": 1303449591,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          18.54981453186638,\n          -5.8578361679578625\n        ],\n        [\n          11.87839000724785,\n          -10.90208397925488\n        ],\n        [\n          30.26548686778207,\n          -10.739366307922724\n        ],\n        [\n          22.455038643838353,\n          -5.695118496625704\n        ],\n        [\n          40.19126481904397,\n          -1.4644590419894659\n        ],\n        [\n          2.603482741314614,\n          0.6508706853286264\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1181,\n      \"versionNonce\": 1544213271,\n      \"isDeleted\": false,\n      \"id\": \"SjkWCQz52AOiHzEzGMPFg\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1263.125423534076,\n      \"y\": 487.90556559524134,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 69.48044565883353,\n      \"height\": 60.5472455026975,\n      \"seed\": 857340183,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1003,\n      \"versionNonce\": 1561382361,\n      \"isDeleted\": false,\n      \"id\": \"ICjA2HRkDMJ0ZoQFIDIO8\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1272.219701140432,\n      \"y\": 499.0798647936875,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#59b6da\",\n      \"width\": 53.51288982419438,\n      \"height\": 39.48733402349843,\n      \"seed\": 164150839,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 979,\n      \"versionNonce\": 1401837623,\n      \"isDeleted\": false,\n      \"id\": \"5D9sQqWIBXUO5ZOBf3kUj\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1298.997457438364,\n      \"y\": 492.4706712625337,\n      \"strokeColor\": \"#82c91e\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 3.063511713352388,\n      \"height\": 2.205728433613729,\n      \"seed\": 1688330071,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"cKxlt68orMI7e-h7oVKRx\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1006,\n      \"versionNonce\": 894151353,\n      \"isDeleted\": false,\n      \"id\": \"9WDqIBF_ZW6siHXKYHljB\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1277.549112368861,\n      \"y\": 557.4922679311202,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 40.35398249037628,\n      \"height\": 7.810448223943735,\n      \"seed\": 100260983,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1522,\n      \"versionNonce\": 1453603159,\n      \"isDeleted\": false,\n      \"id\": \"SzdGju6Z3AcdsR2Op3lhj\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1299.2885151667322,\n      \"y\": 519.240074808582,\n      \"strokeColor\": \"#99d2ea\",\n      \"backgroundColor\": \"#99d2ea\",\n      \"width\": 9.288667053221268,\n      \"height\": 18.46402097648012,\n      \"seed\": 1905603991,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.778923129568891,\n          -6.939225465885939\n        ],\n        [\n          9.288667053221268,\n          5.356595096473355\n        ],\n        [\n          0.6230203511306952,\n          11.524795510594183\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1312,\n      \"versionNonce\": 2144856985,\n      \"isDeleted\": false,\n      \"id\": \"AM8Ols6uc6B8KqXenn16Q\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1298.3990678815992,\n      \"y\": 515.8542383530967,\n      \"strokeColor\": \"#000\",\n      \"backgroundColor\": \"#000000\",\n      \"width\": 16.409603122998895,\n      \"height\": 9.808358962749613,\n      \"seed\": 1051224759,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          7.345815116432727,\n          -7.281963472344416\n        ],\n        [\n          0.11848088897473066,\n          -9.808358962749613\n        ],\n        [\n          -9.063788006566167,\n          -5.151865313767477\n        ],\n        [\n          -0.17772133346203983,\n          -0.8916689966135978\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1288,\n      \"versionNonce\": 2057369207,\n      \"isDeleted\": false,\n      \"id\": \"Yssq30taAhZtbKiO9FAzG\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1287.5947199898799,\n      \"y\": 512.2927688745284,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 8.613693960144035,\n      \"height\": 17.521501861417025,\n      \"seed\": 702020567,\n      \"groupIds\": [\n        \"y7sxTv1UHlQAgzYT5IQIi\",\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.185684322372918,\n          5.984456621681159\n        ],\n        [\n          8.613693960144035,\n          17.521501861417025\n        ],\n        [\n          1.6585373463631312,\n          12.400781246988803\n        ],\n        [\n          0.9095204802636871,\n          2.159340018132377\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 842,\n      \"versionNonce\": 887689337,\n      \"isDeleted\": false,\n      \"id\": \"Wppg3DylzBOIIfB6_s9ew\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1230.0588718274837,\n      \"y\": 573.3605515685075,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 129.27139761875833,\n      \"height\": 47.72265829190373,\n      \"seed\": 1731750135,\n      \"groupIds\": [\n        \"VwtGD5-t-AIPbzcot5qdV\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 19.08906331676149,\n      \"fontFamily\": 1,\n      \"text\": \"SRV02\\n192.168.56.22\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"SRV02\\n192.168.56.22\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 40\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1193,\n      \"versionNonce\": 910757783,\n      \"isDeleted\": false,\n      \"id\": \"OsXZ_-AjlU35m9gOlPvtS\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1530.7475568678317,\n      \"y\": 558.3734779006675,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#868e96\",\n      \"width\": 40.87643519766429,\n      \"height\": 11.749906473822545,\n      \"seed\": 1798068823,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          18.866047014306528,\n          -5.9576990571494886\n        ],\n        [\n          12.080889754775313,\n          -11.08793991191707\n        ],\n        [\n          30.78144512860547,\n          -10.922448271440706\n        ],\n        [\n          22.837846385739585,\n          -5.792207416673119\n        ],\n        [\n          40.87643519766429,\n          -1.4894247642873724\n        ],\n        [\n          2.647866247622004,\n          0.6619665619054733\n        ]\n      ]\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1212,\n      \"versionNonce\": 2051184985,\n      \"isDeleted\": false,\n      \"id\": \"huZRYMhZMFhX190PTk_sL\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1515.9571603472068,\n      \"y\": 486.17982939028104,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 70.66493048341198,\n      \"height\": 61.57943942125872,\n      \"seed\": 1803351927,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1032,\n      \"versionNonce\": 1899497017,\n      \"isDeleted\": false,\n      \"id\": \"h6khX5G-YpPxeMoDqpr_Q\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1525.2064748666555,\n      \"y\": 497.5446251766574,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#59b6da\",\n      \"width\": 54.42516385057778,\n      \"height\": 40.16050397038617,\n      \"seed\": 234680471,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 1008,\n      \"versionNonce\": 1658672599,\n      \"isDeleted\": false,\n      \"id\": \"TqllulP3IVZg-yrzbF9fj\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1552.4407314888208,\n      \"y\": 490.82275980861306,\n      \"strokeColor\": \"#82c91e\",\n      \"backgroundColor\": \"#82c91e\",\n      \"width\": 3.115737675635388,\n      \"height\": 2.243331126457489,\n      \"seed\": 207668663,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"6AoiEoK2dW91-YLQdsgSp\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1035,\n      \"versionNonce\": 1152177945,\n      \"isDeleted\": false,\n      \"id\": \"auZXiaL4Bn_q_sPMP8V4q\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1530.6267405313813,\n      \"y\": 556.9528279873275,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#b2b6b6\",\n      \"width\": 41.04192683814082,\n      \"height\": 7.943598742865901,\n      \"seed\": 1976366807,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1551,\n      \"versionNonce\": 1250067191,\n      \"isDeleted\": false,\n      \"id\": \"24wODDL8JiW0R1dYrpW8a\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1552.736751094722,\n      \"y\": 518.0485212833225,\n      \"strokeColor\": \"#99d2ea\",\n      \"backgroundColor\": \"#99d2ea\",\n      \"width\": 9.44701786776737,\n      \"height\": 18.778790872383322,\n      \"seed\": 14025719,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.928583960389902,\n          -7.05752360258802\n        ],\n        [\n          9.44701786776737,\n          5.447912956383734\n        ],\n        [\n          0.6336414423502509,\n          11.721267269795302\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1341,\n      \"versionNonce\": 1997835257,\n      \"isDeleted\": false,\n      \"id\": \"gf5Ue0Z4fDYUaxK-EC8Cg\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1551.8321407403043,\n      \"y\": 514.6049639559858,\n      \"strokeColor\": \"#000\",\n      \"backgroundColor\": \"#000000\",\n      \"width\": 16.68934983003626,\n      \"height\": 9.97556935173361,\n      \"seed\": 494955799,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          7.471044689258119,\n          -7.406104518711323\n        ],\n        [\n          0.12050072079449521,\n          -9.97556935173361\n        ],\n        [\n          -9.218305140778142,\n          -5.239692992829778\n        ],\n        [\n          -0.1807510811916857,\n          -0.9068699410666883\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 1323,\n      \"versionNonce\": 457509911,\n      \"isDeleted\": false,\n      \"id\": \"-iPzSV0ZAbnmq0FMK248I\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1540.8436030956855,\n      \"y\": 510.9827794588173,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 8.760538006445234,\n      \"height\": 17.820203933084482,\n      \"seed\": 1195422263,\n      \"groupIds\": [\n        \"x8CPTwLDTaQu9kELKmBm2\",\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          8.325231770100144,\n          6.086478103905606\n        ],\n        [\n          8.760538006445234,\n          17.820203933084482\n        ],\n        [\n          1.6868116658372752,\n          12.612186586443586\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 872,\n      \"versionNonce\": 1886561497,\n      \"isDeleted\": false,\n      \"id\": \"3iPzEpimivWqJgo-LP1IU\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1482.6278244536288,\n      \"y\": 574.3299387300013,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 130.87333144529953,\n      \"height\": 48.53622193559225,\n      \"seed\": 385569623,\n      \"groupIds\": [\n        \"Njf-VntQsuRaSfhvuodb8\",\n        \"HoyOh7ZC9P-g2pxFwxIuW\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 19.414488774236894,\n      \"fontFamily\": 1,\n      \"text\": \"SRV03\\n192.168.56.23\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"SRV03\\n192.168.56.23\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 41.000000000000014\n    },\n    {\n      \"id\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n      \"type\": \"rectangle\",\n      \"x\": 893.5820175067391,\n      \"y\": 303.56993169125974,\n      \"width\": 169.3126193900116,\n      \"height\": 180.38370511676985,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"seed\": 279786679,\n      \"version\": 1136,\n      \"versionNonce\": 803620729,\n      \"isDeleted\": false,\n      \"boundElements\": [\n        {\n          \"id\": \"5EnmiI-P42lyF3ONrbFTZ\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"6AoiEoK2dW91-YLQdsgSp\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"l8S7i1jyyXiaBDgV1tqr5\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"cKxlt68orMI7e-h7oVKRx\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"SAhg2CJFAfFnLulnaYOt8\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 916,\n      \"versionNonce\": 1579075735,\n      \"isDeleted\": false,\n      \"id\": \"fAvSvt8t153-tb4euGzc3\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1043.35857112288,\n      \"y\": 369.27886540595165,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#DD4814\",\n      \"width\": 121.75687832837134,\n      \"height\": 121.75497745227408,\n      \"seed\": 2057201689,\n      \"groupIds\": [\n        \"FPK4mFxLxRtOyBf1N8gHR\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          -0.07921308421572881,\n          3.1326417621507425\n        ],\n        [\n          -0.3142987188836881,\n          6.224163727094603\n        ],\n        [\n          -0.7014446651967967,\n          9.270746380759999\n        ],\n        [\n          -1.2368168585536337,\n          12.268555658545207\n        ],\n        [\n          -1.916588509617518,\n          15.213779321643544\n        ],\n        [\n          -2.7369328290519013,\n          18.10258330545334\n        ],\n        [\n          -3.6940375780496986,\n          20.93114809590283\n        ],\n        [\n          -4.784068692009697,\n          23.695639628390563\n        ],\n        [\n          -6.003199381594779,\n          26.39223838884469\n        ],\n        [\n          -7.347610132733612,\n          29.017124863193548\n        ],\n        [\n          -8.813466880824448,\n          31.566457711570628\n        ],\n        [\n          -10.39695738706037,\n          34.036424695169046\n        ],\n        [\n          -12.094254862104936,\n          36.423191749387314\n        ],\n        [\n          -13.901525241356396,\n          38.72293936015357\n        ],\n        [\n          -15.814949010743147,\n          40.931840738131356\n        ],\n        [\n          -17.830699380928287,\n          43.046069093983704\n        ],\n        [\n          -19.944949562575545,\n          45.06180491363917\n        ],\n        [\n          -22.153887316877686,\n          46.97521413249607\n        ],\n        [\n          -24.45367130396847,\n          48.782469961217735\n        ],\n        [\n          -26.840489285041023,\n          50.47976016099736\n        ],\n        [\n          -29.310507195493784,\n          52.06325066723337\n        ],\n        [\n          -31.85989824598994,\n          53.52910741532415\n        ],\n        [\n          -34.48485019772275,\n          54.87352544172786\n        ],\n        [\n          -37.181528986090946,\n          56.092656131313035\n        ],\n        [\n          -39.94611509702236,\n          57.18269452053786\n        ],\n        [\n          -42.774774465915556,\n          58.139806544800535\n        ],\n        [\n          -45.6636875786988,\n          58.960158139499846\n        ],\n        [\n          -48.60903492130038,\n          59.639937065828605\n        ],\n        [\n          -51.6069824291188,\n          60.17531653445045\n        ],\n        [\n          -54.65371058808214,\n          60.562462480763536\n        ],\n        [\n          -57.74538533358883,\n          60.79755539069639\n        ],\n        [\n          -60.87819806446477,\n          60.87677575017707\n        ],\n        [\n          -64.0110944608868,\n          60.79755539069634\n        ],\n        [\n          -67.10285287193989,\n          60.5624624807636\n        ],\n        [\n          -70.1496501459197,\n          60.175316534450275\n        ],\n        [\n          -73.14765949348964,\n          59.63993706582848\n        ],\n        [\n          -76.09306140057795,\n          58.96015813949971\n        ],\n        [\n          -78.9820218025832,\n          58.139806544800614\n        ],\n        [\n          -81.81072846069821,\n          57.182694520537765\n        ],\n        [\n          -84.5753473103216,\n          56.092656131312964\n        ],\n        [\n          -87.27205519974918,\n          54.87352544172779\n        ],\n        [\n          -89.89703261490929,\n          53.52910741532406\n        ],\n        [\n          -92.44644731001647,\n          52.06325066723346\n        ],\n        [\n          -94.91648158981522,\n          50.47976016099739\n        ],\n        [\n          -97.30330866496891,\n          48.78246996121791\n        ],\n        [\n          -99.60310356495712,\n          46.9752141324962\n        ],\n        [\n          -101.81204131925912,\n          45.06180491363929\n        ],\n        [\n          -103.92629695735508,\n          43.04606909398376\n        ],\n        [\n          -105.94204732754048,\n          40.93184073813134\n        ],\n        [\n          -107.85546654988633,\n          38.722939360153546\n        ],\n        [\n          -109.66273147268927,\n          36.42319174938722\n        ],\n        [\n          -111.36001712542844,\n          34.03642469516903\n        ],\n        [\n          -112.94349762817498,\n          31.566457711570607\n        ],\n        [\n          -114.4093498292253,\n          29.01712486319365\n        ],\n        [\n          -115.75374830335467,\n          26.392238388844753\n        ],\n        [\n          -116.97286898945053,\n          23.695639628390474\n        ],\n        [\n          -118.06288691699284,\n          20.931148095902877\n        ],\n        [\n          -119.01997825222094,\n          18.102583305453365\n        ],\n        [\n          -119.8403175699107,\n          15.213779321643521\n        ],\n        [\n          -120.5200804679215,\n          12.268555658545303\n        ],\n        [\n          -121.05544271462705,\n          9.27074638075996\n        ],\n        [\n          -121.44257945318324,\n          6.224163727094528\n        ],\n        [\n          -121.6776661819827,\n          3.132641762150776\n        ],\n        [\n          -121.75687832837136,\n          7.105427357601002e-14\n        ],\n        [\n          -121.67766346796796,\n          -3.132809093243303\n        ],\n        [\n          -121.44256896657087,\n          -6.224491114014874\n        ],\n        [\n          -121.05541992258617,\n          -9.271219272978222\n        ],\n        [\n          -120.52004136337267,\n          -12.269166780796567\n        ],\n        [\n          -119.84025845838342,\n          -15.214510485765615\n        ],\n        [\n          -119.01989640549073,\n          -18.103423598549057\n        ],\n        [\n          -118.06278006153966,\n          -20.93208660507465\n        ],\n        [\n          -116.97273485175396,\n          -23.696669078373596\n        ],\n        [\n          -115.75358551930256,\n          -26.393347866741557\n        ],\n        [\n          -114.40915748940967,\n          -29.018296180842164\n        ],\n        [\n          -112.94327573259555,\n          -31.56769450660329\n        ],\n        [\n          -111.35976521938125,\n          -34.03771241705603\n        ],\n        [\n          -109.66245137499077,\n          -36.424526760496114\n        ],\n        [\n          -107.85515916994449,\n          -38.724312566403086\n        ],\n        [\n          -105.941712665355,\n          -40.93324668307277\n        ],\n        [\n          -103.92593865055873,\n          -43.04750050235237\n        ],\n        [\n          -101.8116630054844,\n          -45.06325269135381\n        ],\n        [\n          -99.60270706301999,\n          -46.97667646074068\n        ],\n        [\n          -97.30289943131824,\n          -48.783946839992055\n        ],\n        [\n          -94.9160632620835,\n          -50.48123976799617\n        ],\n        [\n          -92.44602534465247,\n          -52.06472936482385\n        ],\n        [\n          -89.89660701191272,\n          -53.53059156936324\n        ],\n        [\n          -87.27164050965001,\n          -54.87500095639003\n        ],\n        [\n          -84.57494353311984,\n          -56.094132555383304\n        ],\n        [\n          -81.81034650929097,\n          -57.18416207787886\n        ],\n        [\n          -78.98166895223548,\n          -58.14126387130044\n        ],\n        [\n          -76.09274128892245,\n          -58.961613192479355\n        ],\n        [\n          -73.14738667105601,\n          -59.641385298247464\n        ],\n        [\n          -70.14942825034034,\n          -60.176755047569976\n        ],\n        [\n          -67.10269645374451,\n          -60.563897697278705\n        ],\n        [\n          -64.01101079534054,\n          -60.7989882129104\n        ],\n        [\n          -60.878198064464726,\n          -60.87820170209703\n        ],\n        [\n          -57.745348957264454,\n          -60.79898821291046\n        ],\n        [\n          -54.65363056016823,\n          -60.56389769727871\n        ],\n        [\n          -51.606873300145224,\n          -60.17675504756999\n        ],\n        [\n          -48.6088966912674,\n          -59.641385298247364\n        ],\n        [\n          -45.66352752287113,\n          -58.96161319247935\n        ],\n        [\n          -42.77459258429314,\n          -58.141263871300445\n        ],\n        [\n          -39.945918664870064,\n          -57.18416207787901\n        ],\n        [\n          -37.181325278673846,\n          -56.09413255538324\n        ],\n        [\n          -34.48464649030576,\n          -54.87500095638998\n        ],\n        [\n          -31.859687263308018,\n          -53.53059156936342\n        ],\n        [\n          -29.31028893754677,\n          -52.06472936482392\n        ],\n        [\n          -26.84027830235899,\n          -50.48123976799603\n        ],\n        [\n          -24.453467596551356,\n          -48.783946839992154\n        ],\n        [\n          -22.15369088472539,\n          -46.976676460740535\n        ],\n        [\n          -19.944760405688037,\n          -45.06325269135387\n        ],\n        [\n          -17.830517499305813,\n          -43.04750050235246\n        ],\n        [\n          -15.814781679650485,\n          -40.933246683072824\n        ],\n        [\n          -13.901365185528688,\n          -38.724312566403086\n        ],\n        [\n          -12.09410935680699,\n          -36.42452676049609\n        ],\n        [\n          -10.396833707557128,\n          -34.03771241705598\n        ],\n        [\n          -8.813357751850935,\n          -31.56769450660329\n        ],\n        [\n          -7.347508279024986,\n          -29.018296180842185\n        ],\n        [\n          -6.003119353680958,\n          -26.39334786674169\n        ],\n        [\n          -4.78399593936067,\n          -23.696669078373624\n        ],\n        [\n          -3.6939866511954946,\n          -20.932086605074673\n        ],\n        [\n          -2.7368964527273523,\n          -18.103423598548964\n        ],\n        [\n          -1.9165594085579771,\n          -15.214510485765711\n        ],\n        [\n          -1.236795032758912,\n          -12.269166780796589\n        ],\n        [\n          -0.7014301146669819,\n          -9.271219272978236\n        ],\n        [\n          -0.3142987188836215,\n          -6.224491114014973\n        ],\n        [\n          -0.07920580895081564,\n          -3.132809093243284\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 893,\n      \"versionNonce\": 780202073,\n      \"isDeleted\": false,\n      \"id\": \"po9WVptfybkUevzcn3VKR\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 942.7271169481343,\n      \"y\": 361.1495680738228,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 16.25669218248767,\n      \"height\": 16.256692182487665,\n      \"seed\": 2058091769,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          -1.638686122205307,\n          0.16510849924087168\n        ],\n        [\n          -3.164802070634858,\n          0.6386700420193787\n        ],\n        [\n          -4.5457019128724845,\n          1.3880368771031326\n        ],\n        [\n          -5.7487378976858,\n          2.3805612532597507\n        ],\n        [\n          -6.741262273842411,\n          3.583595419256838\n        ],\n        [\n          -7.49062910892617,\n          4.964495261494463\n        ],\n        [\n          -7.964190651704678,\n          6.490613028740235\n        ],\n        [\n          -8.129299150945547,\n          8.129297332129324\n        ],\n        [\n          -7.964190651704676,\n          9.767214095071607\n        ],\n        [\n          -7.49062910892617,\n          11.292793492714885\n        ],\n        [\n          -6.7412622738424055,\n          12.673347759869824\n        ],\n        [\n          -5.7487378976858,\n          13.876189131347106\n        ],\n        [\n          -4.545701912872482,\n          14.868629841957384\n        ],\n        [\n          -3.1648020706348587,\n          15.61798212651134\n        ],\n        [\n          -1.638686122205308,\n          16.091565495084552\n        ],\n        [\n          1.7763568394002505e-15,\n          16.256692182487665\n        ],\n        [\n          1.6380568117915821,\n          16.09156549508455\n        ],\n        [\n          3.163699868002724,\n          15.61798212651134\n        ],\n        [\n          4.544261410422562,\n          14.868629841957382\n        ],\n        [\n          5.747070043207801,\n          13.876189131347104\n        ],\n        [\n          6.739456189331349,\n          12.673347759869824\n        ],\n        [\n          7.488752090582334,\n          11.292793492714887\n        ],\n        [\n          7.962288169933693,\n          9.767214095071603\n        ],\n        [\n          8.12739303154212,\n          8.129297332129322\n        ],\n        [\n          7.9622881699336965,\n          6.490613028740235\n        ],\n        [\n          7.488752090582338,\n          4.964495261494464\n        ],\n        [\n          6.739456189331345,\n          3.583595419256838\n        ],\n        [\n          5.747070043207799,\n          2.38056125325975\n        ],\n        [\n          4.544261410422566,\n          1.388036877103133\n        ],\n        [\n          3.163699868002724,\n          0.6386700420193778\n        ],\n        [\n          1.638056811791583,\n          0.16510849924087168\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 896,\n      \"versionNonce\": 713530807,\n      \"isDeleted\": false,\n      \"id\": \"DkgmBi5yRenA04XT30erv\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1000.7598297748109,\n      \"y\": 398.09043493470045,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 16.215154057549217,\n      \"height\": 16.213546224006635,\n      \"seed\": 1374942681,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          -1.3360296459756202,\n          0.9623211139301532\n        ],\n        [\n          -2.4206261370562427,\n          2.1352756972040563\n        ],\n        [\n          -3.2417707356294065,\n          3.4742809265231953\n        ],\n        [\n          -3.7874592546124575,\n          4.934739428059273\n        ],\n        [\n          -4.045658405863139,\n          6.47205382798396\n        ],\n        [\n          -4.004364002298788,\n          8.041641302998759\n        ],\n        [\n          -3.6515427557771476,\n          9.59889720401046\n        ],\n        [\n          -2.9751832039506634,\n          11.099238707720572\n        ],\n        [\n          -2.0136478186295586,\n          12.435377482669669\n        ],\n        [\n          -0.8412534307528468,\n          13.519995799544983\n        ],\n        [\n          0.4974171363809585,\n          14.34108947126386\n        ],\n        [\n          1.957766508943548,\n          14.886690687068146\n        ],\n        [\n          3.495190037841721,\n          15.144809810404922\n        ],\n        [\n          5.065112175041857,\n          15.103464479986293\n        ],\n        [\n          6.622928271450757,\n          14.750657783994443\n        ],\n        [\n          8.124048228505005,\n          14.074421911671243\n        ],\n        [\n          9.460056048685919,\n          13.112886526350135\n        ],\n        [\n          10.544601612912253,\n          11.940477587943622\n        ],\n        [\n          11.365695284631123,\n          10.601792470280017\n        ],\n        [\n          11.911325601494996,\n          9.141413996657825\n        ],\n        [\n          12.16949565168608,\n          7.60392499037556\n        ],\n        [\n          12.128208523386622,\n          6.033922825261546\n        ],\n        [\n          11.775452754249084,\n          4.475990324614276\n        ],\n        [\n          11.099231432455666,\n          2.9747103117322586\n        ],\n        [\n          10.137579642896181,\n          1.6395027706901768\n        ],\n        [\n          8.964894244423526,\n          0.5555683287153252\n        ],\n        [\n          7.625874464574592,\n          -0.26511065290433367\n        ],\n        [\n          6.1652122556213556,\n          -0.8105445376159328\n        ],\n        [\n          4.627599569835823,\n          -1.0687364136017146\n        ],\n        [\n          3.0577283594899773,\n          -1.02770391957371\n        ],\n        [\n          1.5002978521207062,\n          -0.6754574189790601\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 895,\n      \"versionNonce\": 1502838073,\n      \"isDeleted\": false,\n      \"id\": \"QNs5OGimBIo0YQ33pvkdw\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 960.3822405424527,\n      \"y\": 369.27886540595284,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 20.543527438555024,\n      \"height\": 58.75647982339908,\n      \"seed\": 1938412217,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0.046296148182129904,\n          -1.4945867691753179\n        ],\n        [\n          0.1833585012389647,\n          -2.964521303241786\n        ],\n        [\n          0.7187852590825647,\n          -5.8194953052731755\n        ],\n        [\n          1.5843053359046335,\n          -8.543078023236177\n        ],\n        [\n          2.7579401564465535,\n          -11.113418199007896\n        ],\n        [\n          4.217718420714598,\n          -13.508675487362776\n        ],\n        [\n          5.941665191082626,\n          -15.70699499254549\n        ],\n        [\n          7.907801892292,\n          -17.68653636933051\n        ],\n        [\n          10.094157224348978,\n          -19.425448359594895\n        ],\n        [\n          4.151902736809587,\n          -29.37799982795789\n        ],\n        [\n          4.151902736809587,\n          -29.37799982795789\n        ],\n        [\n          1.5730977903283758,\n          -27.48021787810315\n        ],\n        [\n          -0.8202170022986,\n          -25.36197721365912\n        ],\n        [\n          -3.0131237103967656,\n          -23.03810482448914\n        ],\n        [\n          -4.990700765659165,\n          -20.52344225098627\n        ],\n        [\n          -6.738030237411219,\n          -17.83282012064629\n        ],\n        [\n          -8.24019965142708,\n          -14.981072698597426\n        ],\n        [\n          -9.482285620583536,\n          -11.983037887600318\n        ],\n        [\n          -10.449370214206038,\n          -8.853546315150716\n        ],\n        [\n          -9.531801073483289,\n          -8.018720580935769\n        ],\n        [\n          -8.709272355763161,\n          -7.089618326532553\n        ],\n        [\n          -7.990201542533335,\n          -6.074547904455229\n        ],\n        [\n          -7.38300247764899,\n          -4.981817667217991\n        ],\n        [\n          -6.896089004965368,\n          -3.81973596733502\n        ],\n        [\n          -6.537873149521426,\n          -2.5966147949529446\n        ],\n        [\n          -6.316774211621066,\n          -1.3207588649534974\n        ],\n        [\n          -6.241206035119497,\n          -0.00047652985085688826\n        ],\n        [\n          -6.316774211621065,\n          1.3191801324705006\n        ],\n        [\n          -6.537873149521426,\n          2.59457044551644\n        ],\n        [\n          -6.89608900496537,\n          3.8173678686105275\n        ],\n        [\n          -7.38300247764899,\n          4.979256773973689\n        ],\n        [\n          -7.990201542533329,\n          6.071906983297043\n        ],\n        [\n          -8.709272355763163,\n          7.0869883182716995\n        ],\n        [\n          -9.531801073483289,\n          8.016185151118627\n        ],\n        [\n          -10.44937021420604,\n          8.85116002826399\n        ],\n        [\n          -9.48322412975545,\n          11.98132092508425\n        ],\n        [\n          -8.241809303785892,\n          14.97993775727324\n        ],\n        [\n          -6.740041848155682,\n          17.832176259702777\n        ],\n        [\n          -4.992846968804235,\n          20.52320216724461\n        ],\n        [\n          -3.015135321141228,\n          23.038181214770574\n        ],\n        [\n          -0.8218248358411877,\n          25.36227186188752\n        ],\n        [\n          1.5721592811564573,\n          27.480654393997064\n        ],\n        [\n          4.151902736809584,\n          29.378479995441197\n        ],\n        [\n          10.094157224348985,\n          19.423065710340612\n        ],\n        [\n          10.094157224348985,\n          19.423065710340612\n        ],\n        [\n          7.907801892291995,\n          17.684961274479953\n        ],\n        [\n          5.941665191082625,\n          15.706060121006029\n        ],\n        [\n          4.217718420714604,\n          13.508217145674164\n        ],\n        [\n          2.757940156446555,\n          11.113301794769523\n        ],\n        [\n          1.584305335904634,\n          8.543161688782508\n        ],\n        [\n          0.7187852590825647,\n          5.819658998733398\n        ],\n        [\n          0.18335850123896424,\n          2.9646558956424114\n        ],\n        [\n          0.046296148182129904,\n          1.4946667970892022\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 897,\n      \"versionNonce\": 1498992343,\n      \"isDeleted\": false,\n      \"id\": \"-f2Rh5dGjAdREvQlwi6Kj\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 984.1226557886606,\n      \"y\": 345.5360675104861,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 50.87606566581782,\n      \"height\": 33.20282484308948,\n      \"seed\": 605098905,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          2.2977432752867406,\n          0.1097510086275586\n        ],\n        [\n          4.533206645409167,\n          0.4322816897439514\n        ],\n        [\n          6.696317506115195,\n          0.9574939756699439\n        ],\n        [\n          8.776999615520289,\n          1.675297073991198\n        ],\n        [\n          10.765162181210117,\n          2.575592917028489\n        ],\n        [\n          12.650728961300139,\n          3.6482943499999276\n        ],\n        [\n          14.423630989170718,\n          4.88330330522628\n        ],\n        [\n          16.07378474767242,\n          6.270525352660773\n        ],\n        [\n          17.591099444390903,\n          7.799869699889078\n        ],\n        [\n          18.96551338797144,\n          9.461241916864399\n        ],\n        [\n          20.186935785999708,\n          11.244547573539936\n        ],\n        [\n          21.245297671856026,\n          13.139695877501378\n        ],\n        [\n          22.130508253126113,\n          15.136588761069504\n        ],\n        [\n          22.832498563190278,\n          17.225131794197523\n        ],\n        [\n          23.341185084899166,\n          19.395237822103553\n        ],\n        [\n          23.646484301103275,\n          21.63680877710834\n        ],\n        [\n          35.22776023520919,\n          21.46611651205781\n        ],\n        [\n          35.22776023520919,\n          21.46611651205781\n        ],\n        [\n          34.86003197091034,\n          18.153946675637258\n        ],\n        [\n          34.19355222881611,\n          14.941804456307336\n        ],\n        [\n          33.2428933645184,\n          11.843887533517583\n        ],\n        [\n          32.022642284138804,\n          8.874404499614956\n        ],\n        [\n          30.547385893799017,\n          6.047556671681482\n        ],\n        [\n          28.831703824355806,\n          3.3775490044316516\n        ],\n        [\n          26.890175706665907,\n          0.8785791773150233\n        ],\n        [\n          24.73738844685095,\n          -1.4351442173214668\n        ],\n        [\n          23.55782792304913,\n          -1.060879127511246\n        ],\n        [\n          22.34460474856158,\n          -0.8158154670349589\n        ],\n        [\n          21.109039235570478,\n          -0.7029106310738591\n        ],\n        [\n          19.862429870463338,\n          -0.7251402029714757\n        ],\n        [\n          18.616089690157438,\n          -0.8854688531739825\n        ],\n        [\n          17.381324456305194,\n          -1.1868612521275423\n        ],\n        [\n          16.169447205823868,\n          -1.6322857079107829\n        ],\n        [\n          14.991763700365887,\n          -2.224710528602327\n        ],\n        [\n          13.887160230814164,\n          -2.949137755613741\n        ],\n        [\n          12.893642780998903,\n          -3.777092002131984\n        ],\n        [\n          12.014186934263599,\n          -4.6972311301801515\n        ],\n        [\n          11.251804650276277,\n          -5.698198451251574\n        ],\n        [\n          10.609486062910259,\n          -6.768653646185575\n        ],\n        [\n          10.09022130603886,\n          -7.8972436641079256\n        ],\n        [\n          9.697015064065194,\n          -9.072624548225507\n        ],\n        [\n          9.432850195597677,\n          -10.283445066480297\n        ],\n        [\n          7.111029431129076,\n          -10.84241094390326\n        ],\n        [\n          4.75948920954977,\n          -11.243225294144628\n        ],\n        [\n          2.386290524367385,\n          -11.484793189837148\n        ],\n        [\n          -0.0004765298508546678,\n          -11.566016065981145\n        ],\n        [\n          -2.0317523153296806,\n          -11.509409048621496\n        ],\n        [\n          -4.051336750116484,\n          -11.336195904283603\n        ],\n        [\n          -6.054315392772262,\n          -11.04752066837277\n        ],\n        [\n          -8.035784714755394,\n          -10.644531013926734\n        ],\n        [\n          -9.990826636994429,\n          -10.128372795167026\n        ],\n        [\n          -11.914537630947708,\n          -9.5001936851314\n        ],\n        [\n          -13.801999617543814,\n          -8.761141356857612\n        ],\n        [\n          -15.648305430608632,\n          -7.912359845750952\n        ],\n        [\n          -10.000710084359147,\n          2.2084976007758312\n        ],\n        [\n          -10.000710084359147,\n          2.2084976007758312\n        ],\n        [\n          -7.602539052412382,\n          1.2479189127888883\n        ],\n        [\n          -5.121353610340339,\n          0.5563249562647745\n        ],\n        [\n          -2.5796707030041466,\n          0.13869565002656636\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 897,\n      \"versionNonce\": 545353241,\n      \"isDeleted\": false,\n      \"id\": \"07QbQy7SlS7FR5mHQ_OcP\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 984.1226557886631,\n      \"y\": 393.01975718201027,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 50.87654219566864,\n      \"height\": 33.206164189677914,\n      \"seed\": 1203583097,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          -2.5795433858684236,\n          -0.1387756779404492\n        ],\n        [\n          -5.121098976068896,\n          -0.5564340852382554\n        ],\n        [\n          -7.602164376270109,\n          -1.247998940702777\n        ],\n        [\n          -10.000229916875844,\n          -2.208501238408282\n        ],\n        [\n          -15.647828900757778,\n          7.911406786049239\n        ],\n        [\n          -15.647828900757778,\n          7.911406786049239\n        ],\n        [\n          -13.801704969315425,\n          8.761114074614227\n        ],\n        [\n          -11.91433028589811,\n          9.500964863210642\n        ],\n        [\n          -9.990630204842168,\n          10.129824210514279\n        ],\n        [\n          -8.035526442851499,\n          10.646535349406285\n        ],\n        [\n          -6.053944354262443,\n          11.049948788032667\n        ],\n        [\n          -4.050802018146447,\n          11.338907759274544\n        ],\n        [\n          -2.0310211512073755,\n          11.512262771277966\n        ],\n        [\n          0.00047652985085289146,\n          11.568878882718728\n        ],\n        [\n          2.387287235658486,\n          11.487526870622787\n        ],\n        [\n          4.760449544516376,\n          11.245362403208581\n        ],\n        [\n          7.111829710267919,\n          10.843469494946007\n        ],\n        [\n          9.433323087816074,\n          10.282968536629443\n        ],\n        [\n          9.69750978207829,\n          9.072262603796805\n        ],\n        [\n          10.09075967564135,\n          7.8971690926427085\n        ],\n        [\n          10.610068084102135,\n          6.7689282874354975\n        ],\n        [\n          11.252401221997959,\n          5.698795022973254\n        ],\n        [\n          12.014761680190574,\n          4.6980095835243\n        ],\n        [\n          12.894115673217303,\n          3.7778268038867386\n        ],\n        [\n          13.887458516675004,\n          2.949479693063979\n        ],\n        [\n          14.99176370036589,\n          2.2242376363839167\n        ],\n        [\n          16.170283861287206,\n          1.6308524807257605\n        ],\n        [\n          17.382597627662435,\n          1.1849805961512585\n        ],\n        [\n          18.617471990488166,\n          0.8835227198136106\n        ],\n        [\n          19.86368121602589,\n          0.7234159651905117\n        ],\n        [\n          21.109999570537106,\n          0.7015537941702714\n        ],\n        [\n          22.345208595548172,\n          0.8148660449656919\n        ],\n        [\n          23.558082557320592,\n          1.0602680052597648\n        ],\n        [\n          24.737388446850964,\n          1.4346676874705953\n        ],\n        [\n          26.89031393669896,\n          -0.8790557071658753\n        ],\n        [\n          28.83191480703786,\n          -3.378021896650049\n        ],\n        [\n          30.547647803335387,\n          -6.048036839164791\n        ],\n        [\n          32.02294056999967,\n          -8.874884667098264\n        ],\n        [\n          33.24324985249844,\n          -11.844364063368438\n        ],\n        [\n          34.19401784576962,\n          -14.942280986158185\n        ],\n        [\n          34.86069402001611,\n          -18.15442684312056\n        ],\n        [\n          35.228713294910854,\n          -21.46659304190866\n        ],\n        [\n          23.64410528948141,\n          -21.63728530695919\n        ],\n        [\n          23.64410528948141,\n          -21.63728530695919\n        ],\n        [\n          23.33922076337652,\n          -19.395165069454553\n        ],\n        [\n          22.830919830707288,\n          -17.22465526434667\n        ],\n        [\n          22.129271458093335,\n          -15.135824858255177\n        ],\n        [\n          21.244359162684127,\n          -13.138764643594378\n        ],\n        [\n          20.18625918636411,\n          -11.243543586983932\n        ],\n        [\n          18.965055046282824,\n          -9.460252480838186\n        ],\n        [\n          17.59083025958965,\n          -7.79896029177675\n        ],\n        [\n          16.073661068169137,\n          -6.269750536949084\n        ],\n        [\n          14.42363098917071,\n          -4.882699458239705\n        ],\n        [\n          12.650816264478923,\n          -3.6478905727980555\n        ],\n        [\n          10.76530041124319,\n          -2.5754001225086762\n        ],\n        [\n          8.77715967134806,\n          -1.6753043492560993\n        ],\n        [\n          6.696484837207861,\n          -0.957686770189754\n        ],\n        [\n          4.533344875442237,\n          -0.43262362719418457\n        ],\n        [\n          2.2978233032006212,\n          -0.11019116215392355\n        ],\n        [\n          0,\n          -0.0004728922184047496\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 896,\n      \"versionNonce\": 891739127,\n      \"isDeleted\": false,\n      \"id\": \"cKx3lSU7PeZafbwDHjet1\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 1000.7569633204448,\n      \"y\": 340.46252694106204,\n      \"strokeColor\": \"#dd4814\",\n      \"backgroundColor\": \"#FFF\",\n      \"width\": 16.214310126820983,\n      \"height\": 16.21424464943689,\n      \"seed\": 1884406105,\n      \"groupIds\": [\n        \"oMrK3TH5nSfRVrWId80K5\",\n        \"YOhVLb1oMInqrd7QHv7Tt\",\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          1.5011417828489422,\n          0.6762249594258607\n        ],\n        [\n          3.059008806112128,\n          1.0292862896891504\n        ],\n        [\n          4.628989145431456,\n          1.0710863241639539\n        ],\n        [\n          6.166470876448814,\n          0.8135237585919004\n        ],\n        [\n          7.6268420748061025,\n          0.26850092634707323\n        ],\n        [\n          8.965505366675004,\n          -0.5520798391964554\n        ],\n        [\n          10.137841552432532,\n          -1.6363234799294961\n        ],\n        [\n          11.09923870772056,\n          -2.9723203872130677\n        ],\n        [\n          11.775736489580115,\n          -4.473467626510686\n        ],\n        [\n          12.128928774611584,\n          -6.031372844914586\n        ],\n        [\n          12.170746997248635,\n          -7.601456856758716\n        ],\n        [\n          11.913122591924951,\n          -9.13914593282569\n        ],\n        [\n          11.367994268339086,\n          -10.59986270626565\n        ],\n        [\n          10.547293460924724,\n          -11.939031629045012\n        ],\n        [\n          9.462958879380459,\n          -13.112075334313921\n        ],\n        [\n          8.126914682875036,\n          -14.07441645522255\n        ],\n        [\n          6.625787450555896,\n          -14.74989206236384\n        ],\n        [\n          5.067934977822506,\n          -15.102156751120749\n        ],\n        [\n          3.4979109869137925,\n          -15.143158325272937\n        ],\n        [\n          1.9602692000686606,\n          -14.884844588600105\n        ],\n        [\n          0.4995851653207355,\n          -14.339157888433272\n        ],\n        [\n          -0.8395873950910682,\n          -13.518046028552156\n        ],\n        [\n          -2.0127020341927455,\n          -12.4334549939202\n        ],\n        [\n          -2.9751759286857657,\n          -11.097328950684679\n        ],\n        [\n          -3.6504805671019556,\n          -9.596836485227946\n        ],\n        [\n          -4.0026106634582295,\n          -8.03949328103745\n        ],\n        [\n          -4.043563129572347,\n          -6.469911262471312\n        ],\n        [\n          -3.7853057762024767,\n          -4.9327096291525585\n        ],\n        [\n          -3.2398427904312856,\n          -3.472502124255492\n        ],\n        [\n          -2.419141983016932,\n          -2.1339043097706747\n        ],\n        [\n          -1.3352002657771815,\n          -0.9615317476886582\n        ],\n        [\n          0,\n          0\n        ],\n        [\n          0,\n          0\n        ]\n      ]\n    },\n    {\n      \"id\": \"ANpLlH9b4bpHbYI2jx9SY\",\n      \"type\": \"text\",\n      \"x\": 931.4255845647491,\n      \"y\": 438.9225098516119,\n      \"width\": 100.18808099312358,\n      \"height\": 16.618264290489687,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 535973721,\n      \"version\": 622,\n      \"versionNonce\": 977158905,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"Ubuntu jumpbox\",\n      \"fontSize\": 13.294611432391749,\n      \"fontFamily\": 1,\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 11,\n      \"containerId\": null,\n      \"originalText\": \"Ubuntu jumpbox\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"id\": \"yDqC0vP8PztDo8wtSuXpT\",\n      \"type\": \"text\",\n      \"x\": 935.6556882023284,\n      \"y\": 457.6558259608914,\n      \"width\": 92.9957420544854,\n      \"height\": 16.618264290489687,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"hachure\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"kNR5JPF6F8-Hue2_uOEJe\",\n        \"WN2HXmwDJQbxO8nqWe8yg\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 352397047,\n      \"version\": 630,\n      \"versionNonce\": 1106658583,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"192.168.56.100\",\n      \"fontSize\": 13.294611432391749,\n      \"fontFamily\": 1,\n      \"textAlign\": \"left\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 11,\n      \"containerId\": null,\n      \"originalText\": \"192.168.56.100\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"id\": \"YVuKEDAbE4-UKuRyM2zKo\",\n      \"type\": \"rectangle\",\n      \"x\": 846.1345092947488,\n      \"y\": 378.3641412145678,\n      \"width\": 74.90211824997922,\n      \"height\": 89.18980554621794,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 3\n      },\n      \"seed\": 1126937945,\n      \"version\": 187,\n      \"versionNonce\": 255560247,\n      \"isDeleted\": false,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"text\",\n      \"version\": 2105,\n      \"versionNonce\": 1002608825,\n      \"isDeleted\": false,\n      \"id\": \"q1Z162M8jlXNPgOu7uE6d\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 853.6037927731572,\n      \"y\": 423.29626201872316,\n      \"strokeColor\": \"#000000\",\n      \"backgroundColor\": \"#364fc7\",\n      \"width\": 57.21135267636953,\n      \"height\": 32.14120936874693,\n      \"seed\": 190491641,\n      \"groupIds\": [\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"boundElements\": [\n        {\n          \"id\": \"5H_8bJE7xZuZg1sOmEEq6\",\n          \"type\": \"arrow\"\n        },\n        {\n          \"id\": \"cMIoGo9YKI2HKyZ8oisu_\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"fontSize\": 12.856483747498771,\n      \"fontFamily\": 1,\n      \"text\": \"Public IP\\nAddress\",\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"containerId\": null,\n      \"originalText\": \"Public IP\\nAddress\",\n      \"lineHeight\": 1.25,\n      \"baseline\": 27\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 946,\n      \"versionNonce\": 1239100247,\n      \"isDeleted\": false,\n      \"id\": \"001M3swpLRvx_vtPiGUgm\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 860.1435827743173,\n      \"y\": 395.0150150769979,\n      \"strokeColor\": \"#59b4d9\",\n      \"backgroundColor\": \"#59b4d9\",\n      \"width\": 44.9976931162457,\n      \"height\": 25.712967494997535,\n      \"seed\": 1458881753,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"KZNLIFHdFxYfL0x7VkmSa\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 674,\n      \"versionNonce\": 893458841,\n      \"isDeleted\": false,\n      \"id\": \"17KUh3liZT_XnKQSVDrOf\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 860.3173190411758,\n      \"y\": 388.7605094701064,\n      \"strokeColor\": \"#b3b4b5\",\n      \"backgroundColor\": \"#b3b4b5\",\n      \"width\": 44.302748048813505,\n      \"height\": 11.119121078917706,\n      \"seed\": 1570292153,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"line\",\n      \"version\": 684,\n      \"versionNonce\": 237611127,\n      \"isDeleted\": false,\n      \"id\": \"ut7j7xP15-glEg-Yxv_n1\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 4,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 2,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 875.9535830584045,\n      \"y\": 393.10391614155844,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#59b4d9\",\n      \"width\": 25.01802242756535,\n      \"height\": 0.1737362668581942,\n      \"seed\": 1818895001,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          25.01802242756535,\n          0.1737362668581942\n        ]\n      ]\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 697,\n      \"versionNonce\": 16547449,\n      \"isDeleted\": false,\n      \"id\": \"PYbhZtBfC_dCfC6AVPOTU\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 4,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 864.3893749136021,\n      \"y\": 391.63036930175906,\n      \"strokeColor\": \"#59b4d9\",\n      \"backgroundColor\": \"#59b4d9\",\n      \"width\": 4.72882160827512,\n      \"height\": 4.35938242012891,\n      \"seed\": 1612474233,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"KZNLIFHdFxYfL0x7VkmSa\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"arrow\",\n      \"version\": 2702,\n      \"versionNonce\": 2045477271,\n      \"isDeleted\": false,\n      \"id\": \"KZNLIFHdFxYfL0x7VkmSa\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 869.7228699204347,\n      \"y\": 393.67208308542865,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#59b4d9\",\n      \"width\": 6.317383983935549,\n      \"height\": 0.01084707764919542,\n      \"seed\": 854790233,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"startBinding\": {\n        \"elementId\": \"PYbhZtBfC_dCfC6AVPOTU\",\n        \"focus\": 0.06564010348681451,\n        \"gap\": 1\n      },\n      \"endBinding\": {\n        \"elementId\": \"001M3swpLRvx_vtPiGUgm\",\n        \"gap\": 3.2170976246970895,\n        \"focus\": -0.9489632626919575\n      },\n      \"lastCommittedPoint\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\",\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          -6.317383983935549,\n          -0.01084707764919542\n        ]\n      ]\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 635,\n      \"versionNonce\": 230180697,\n      \"isDeleted\": false,\n      \"id\": \"VwmvkBiL22cDVY2npZqLz\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 870.9494747412251,\n      \"y\": 409.51150914762565,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 4.489565753094957,\n      \"height\": 3.979387826606734,\n      \"seed\": 1254202681,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 661,\n      \"versionNonce\": 2119513783,\n      \"isDeleted\": false,\n      \"id\": \"sGgvirVMpIGaiCMIYX61X\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 880.5408197592,\n      \"y\": 409.6645625255721,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 4.489565753094957,\n      \"height\": 3.979387826606734,\n      \"seed\": 116100633,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"ellipse\",\n      \"version\": 676,\n      \"versionNonce\": 633861177,\n      \"isDeleted\": false,\n      \"id\": \"F5t-e2OvVH4PppXZ1meYU\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 889.5199512653899,\n      \"y\": 409.25642018438174,\n      \"strokeColor\": \"#fff\",\n      \"backgroundColor\": \"#fff\",\n      \"width\": 4.489565753094957,\n      \"height\": 3.979387826606734,\n      \"seed\": 241459961,\n      \"groupIds\": [\n        \"Q93HWjw5tQi9ya54L4UKR\",\n        \"3NLUngpjgmEDYF_wh-KKK\",\n        \"RG-Fo3U4WxZ02FFig6jDC\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 460,\n      \"versionNonce\": 1549578489,\n      \"isDeleted\": false,\n      \"id\": \"HBV6GFmKFga3QlsG4jsS3\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 533.5656031965165,\n      \"y\": 620.4959025516371,\n      \"strokeColor\": \"#343a40\",\n      \"backgroundColor\": \"#ced4da\",\n      \"width\": 77.95193665608433,\n      \"height\": 51.96795777072297,\n      \"seed\": 751293977,\n      \"groupIds\": [\n        \"NQHJFAj9KunAAW5Y2Plvz\",\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"e1j7blQ1XneZeqq8jPxjG\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 570,\n      \"versionNonce\": 700299031,\n      \"isDeleted\": false,\n      \"id\": \"ogVX7dRLL-_fX6DjLxMJD\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 526.1307933872436,\n      \"y\": 678.2481726383328,\n      \"strokeColor\": \"#343a40\",\n      \"backgroundColor\": \"#ced4da\",\n      \"width\": 91.5950397887827,\n      \"height\": 12.537724077551774,\n      \"seed\": 1098361593,\n      \"groupIds\": [\n        \"NQHJFAj9KunAAW5Y2Plvz\",\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 739,\n      \"versionNonce\": 594422233,\n      \"isDeleted\": false,\n      \"id\": \"sHLf8lm2U8SAREHuN3VXO\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 593.6608588706778,\n      \"y\": 682.839451878,\n      \"strokeColor\": \"#343a40\",\n      \"backgroundColor\": \"#343a40\",\n      \"width\": 16.412842239236777,\n      \"height\": 3.1638622965655476,\n      \"seed\": 1595532249,\n      \"groupIds\": [\n        \"NQHJFAj9KunAAW5Y2Plvz\",\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 841,\n      \"versionNonce\": 826588215,\n      \"isDeleted\": false,\n      \"id\": \"tRKiaOkCLePOfA4s2Ro11\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 564.5827570194542,\n      \"y\": 673.2742867953597,\n      \"strokeColor\": \"#343a40\",\n      \"backgroundColor\": \"#343a40\",\n      \"width\": 16.412842239236777,\n      \"height\": 3.1638622965655476,\n      \"seed\": 29491385,\n      \"groupIds\": [\n        \"NQHJFAj9KunAAW5Y2Plvz\",\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"type\": \"rectangle\",\n      \"version\": 1168,\n      \"versionNonce\": 2141030073,\n      \"isDeleted\": false,\n      \"id\": \"iyDGxVpbf7o0hyIpg-1CQ\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 2,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"angle\": 0,\n      \"x\": 540.2601359608269,\n      \"y\": 626.5080776804144,\n      \"strokeColor\": \"#343a40\",\n      \"backgroundColor\": \"#343a40\",\n      \"width\": 64.66238398560861,\n      \"height\": 40.55831658431314,\n      \"seed\": 1460896153,\n      \"groupIds\": [\n        \"NQHJFAj9KunAAW5Y2Plvz\",\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 1\n      },\n      \"boundElements\": [\n        {\n          \"id\": \"cMIoGo9YKI2HKyZ8oisu_\",\n          \"type\": \"arrow\"\n        }\n      ],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false\n    },\n    {\n      \"id\": \"QDqW1cWW2zpHMG_bfkKqs\",\n      \"type\": \"text\",\n      \"x\": 541.9762478323058,\n      \"y\": 696.0719953022088,\n      \"width\": 59.904130898657954,\n      \"height\": 33.51846580833981,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"8M6TvdStESdvKBtkTs6US\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 1274093559,\n      \"version\": 83,\n      \"versionNonce\": 2012093783,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"User\",\n      \"fontSize\": 26.81477264667185,\n      \"fontFamily\": 1,\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 23,\n      \"containerId\": null,\n      \"originalText\": \"User\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"id\": \"cMIoGo9YKI2HKyZ8oisu_\",\n      \"type\": \"arrow\",\n      \"x\": 568.7540146490983,\n      \"y\": 616.5532261351875,\n      \"width\": 269.81538376558444,\n      \"height\": 187.28361931964116,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 1441062425,\n      \"version\": 287,\n      \"versionNonce\": 554588791,\n      \"isDeleted\": false,\n      \"boundElements\": [],\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          20.103891339396455,\n          -181.99312159874734\n        ],\n        [\n          269.81538376558444,\n          -187.28361931964116\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"iyDGxVpbf7o0hyIpg-1CQ\",\n        \"focus\": -0.20760313214837897,\n        \"gap\": 9.954851545226916\n      },\n      \"endBinding\": {\n        \"elementId\": \"q1Z162M8jlXNPgOu7uE6d\",\n        \"focus\": 0.6609140883548593,\n        \"gap\": 15.034394358474572\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": \"arrow\"\n    },\n    {\n      \"id\": \"vAokcSMGJD8JOjx_pqrs_\",\n      \"type\": \"text\",\n      \"x\": 568.8255276482058,\n      \"y\": 487.4650817453783,\n      \"width\": 31.599960327148438,\n      \"height\": 25,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"solid\",\n      \"roughness\": 1,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 1763285657,\n      \"version\": 95,\n      \"versionNonce\": 689042777,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358773,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"ssh\",\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 18,\n      \"containerId\": null,\n      \"originalText\": \"ssh\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    },\n    {\n      \"id\": \"5EnmiI-P42lyF3ONrbFTZ\",\n      \"type\": \"arrow\",\n      \"x\": 1074.5255967665473,\n      \"y\": 396.5726756511387,\n      \"width\": 540.2534995094286,\n      \"height\": 37.04769399014752,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 880750297,\n      \"version\": 183,\n      \"versionNonce\": 1830676215,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358774,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          436.99511174582904,\n          27.420643387404695\n        ],\n        [\n          540.2534995094286,\n          -9.627050602742829\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n        \"focus\": -0.0338306515364628,\n        \"gap\": 11.630959869796413\n      },\n      \"endBinding\": {\n        \"elementId\": \"yN10xzW1r35OxRKCg_xMP\",\n        \"focus\": -0.7474214780713206,\n        \"gap\": 11.747584697238977\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"6AoiEoK2dW91-YLQdsgSp\",\n      \"type\": \"arrow\",\n      \"x\": 1076.6417958549048,\n      \"y\": 397.5266204901835,\n      \"width\": 475.9464130599106,\n      \"height\": 83.6128846594089,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 252254455,\n      \"version\": 221,\n      \"versionNonce\": 1766942713,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358774,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          385.14823408106986,\n          31.74298632536295\n        ],\n        [\n          475.9464130599106,\n          83.6128846594089\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n        \"focus\": -0.044719394158033186,\n        \"gap\": 13.747158958153875\n      },\n      \"endBinding\": {\n        \"elementId\": \"TqllulP3IVZg-yrzbF9fj\",\n        \"focus\": 6.983484088284758,\n        \"gap\": 9.768019090227178\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"l8S7i1jyyXiaBDgV1tqr5\",\n      \"type\": \"arrow\",\n      \"x\": 1075.583696310726,\n      \"y\": 394.46079616958536,\n      \"width\": 337.5337545930254,\n      \"height\": 28.57756888456061,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 1790548057,\n      \"version\": 163,\n      \"versionNonce\": 483651607,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358774,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          281.45447875155105,\n          20.004298219192364\n        ],\n        [\n          337.5337545930254,\n          -8.573270665368245\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n        \"focus\": -0.06464881033211498,\n        \"gap\": 12.689059413975144\n      },\n      \"endBinding\": {\n        \"elementId\": \"rWHSJYGi-z3aEn2JRzgPA\",\n        \"focus\": -0.5258663147656351,\n        \"gap\": 4.122175285811579\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"cKxlt68orMI7e-h7oVKRx\",\n      \"type\": \"arrow\",\n      \"x\": 1075.583696310726,\n      \"y\": 397.5266204901834,\n      \"width\": 225.3752029100765,\n      \"height\": 84.6479635343012,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 1223543639,\n      \"version\": 234,\n      \"versionNonce\": 1051984089,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954358774,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          168.2378275244232,\n          17.047159322880105\n        ],\n        [\n          225.3752029100765,\n          84.6479635343012\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n        \"focus\": -0.06174908744841584,\n        \"gap\": 12.689059413975144\n      },\n      \"endBinding\": {\n        \"elementId\": \"5D9sQqWIBXUO5ZOBf3kUj\",\n        \"focus\": 5.612789308193268,\n        \"gap\": 10.303516029969497\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"SAhg2CJFAfFnLulnaYOt8\",\n      \"type\": \"arrow\",\n      \"x\": 1075.583696310726,\n      \"y\": 396.4685209460048,\n      \"width\": 138.61104028741784,\n      \"height\": 22.22009042775403,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 180038489,\n      \"version\": 136,\n      \"versionNonce\": 1757623159,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954361715,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          90.99656079937358,\n          6.348597265072613\n        ],\n        [\n          138.61104028741784,\n          -15.871493162681418\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": {\n        \"elementId\": \"Z7ZIS3Fwo9hZrSSEQARRy\",\n        \"focus\": -0.04250656774231881,\n        \"gap\": 12.689059413975144\n      },\n      \"endBinding\": {\n        \"elementId\": \"FLuHTL7vlxV7h0XCrkNXu\",\n        \"focus\": -0.4543785686983688,\n        \"gap\": 1\n      },\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"yefDBe5_BH_bWFBYnLcdl\",\n      \"type\": \"line\",\n      \"x\": 561.3473178398472,\n      \"y\": 117.13024128281134,\n      \"width\": 74.06696809251343,\n      \"height\": 0,\n      \"angle\": 0,\n      \"strokeColor\": \"#1971c2\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"MeV0d-fYHW8nH43woqy6_\"\n      ],\n      \"frameId\": null,\n      \"roundness\": {\n        \"type\": 2\n      },\n      \"seed\": 1549472025,\n      \"version\": 182,\n      \"versionNonce\": 495260793,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954416242,\n      \"link\": null,\n      \"locked\": false,\n      \"points\": [\n        [\n          0,\n          0\n        ],\n        [\n          74.06696809251343,\n          0\n        ]\n      ],\n      \"lastCommittedPoint\": null,\n      \"startBinding\": null,\n      \"endBinding\": null,\n      \"startArrowhead\": null,\n      \"endArrowhead\": null\n    },\n    {\n      \"id\": \"AWeMRml6oGOy65lV5ByOH\",\n      \"type\": \"text\",\n      \"x\": 655.0375165897938,\n      \"y\": 101.25874812012981,\n      \"width\": 113.119873046875,\n      \"height\": 25,\n      \"angle\": 0,\n      \"strokeColor\": \"#1e1e1e\",\n      \"backgroundColor\": \"#ffffff\",\n      \"fillStyle\": \"solid\",\n      \"strokeWidth\": 1,\n      \"strokeStyle\": \"dashed\",\n      \"roughness\": 0,\n      \"opacity\": 100,\n      \"groupIds\": [\n        \"MeV0d-fYHW8nH43woqy6_\"\n      ],\n      \"frameId\": null,\n      \"roundness\": null,\n      \"seed\": 813013239,\n      \"version\": 148,\n      \"versionNonce\": 945769367,\n      \"isDeleted\": false,\n      \"boundElements\": null,\n      \"updated\": 1689954416242,\n      \"link\": null,\n      \"locked\": false,\n      \"text\": \"provisionning\",\n      \"fontSize\": 20,\n      \"fontFamily\": 1,\n      \"textAlign\": \"center\",\n      \"verticalAlign\": \"top\",\n      \"baseline\": 18,\n      \"containerId\": null,\n      \"originalText\": \"provisionning\",\n      \"lineHeight\": 1.25,\n      \"isFrameName\": false\n    }\n  ],\n  \"appState\": {\n    \"gridSize\": null,\n    \"viewBackgroundColor\": \"#ffffff\"\n  },\n  \"files\": {}\n}"
  },
  {
    "path": "docs/mkdocs/docs/index.md",
    "content": "---\ntitle: Game Of Active Directory\n---\n#\n\n<div align=\"center\">\n<img alt=\"GOAD\" src=\"./img/logo_GOAD3.png\">\n</div>\n\nWelcome to [GOAD](https://github.com/Orange-Cyberdefense/GOAD/) documentation !\n\nGame Of Active Directory is a free pentest active directory LAB(s) project (1).\n{ .annotate }\n\n1.  GOAD is free if you use your own computer, obviously we will not pay your electricity bill and your cloud provider invoice ;)\n\nThe purpose of this tool is to give pentesters a vulnerable Active directory environment ready to use to practice usual attack techniques.\nThe idea behind this project is to give you an environment where you can try and train your pentest skills without having the pain to build all by yourself.\nThis repository was build for pentest practice :slight_smile:\n\n\n!!! note\n    GOAD main labs (GOAD/GOAD-Light/SCCM) are not pro labs environments (like those you can find on HTB). Theses labs give you an environment to practice a lot of vulnerability and missconfig exploitations. Sure you can use them like pro labs, but it will certainly be too easy due to the number of vulns. Consider more GOAD like a DVWA but for Active Directory. If you want a chall deploy the lab NHA.\n\n!!! warning\n    This lab is extremely vulnerable, do not reuse recipe to build your production environment and do not deploy this environment on internet without isolation (this is a recommendation, use it as your own risk).\n\n!!! info \"Windows Licenses\"\n    This lab use free windows VM only (180 days). After that delay enter a license on each server or rebuild all the lab (may be it's time for an update ;))\n\n!!! example \"\"\n    **:heart: Sponsor**<br>\n    This lab is created and maintained mainly by his creator (Cyril Servières a.k.a @m4yfly) on personal time (~80% personal time / ~20% at Orange Cyberdefense).\n    If you like it maybe consider sponsoring me : [https://github.com/sponsors/Mayfly277](https://github.com/sponsors/Mayfly277)"
  },
  {
    "path": "docs/mkdocs/docs/installation/index.md",
    "content": "# 🚀 Installation\n\nIn the last version, GOAD use no more bash for the installation/management script.\nThe goad management script is now written in :simple-python: python to permit more flexibility and cover the needs to create a Windows WSL support.\n\n- First prepare you system for GOAD execution:\n    - :material-linux: [Linux](linux.md)\n    - :material-microsoft-windows: [Windows](windows.md)\n\n- Installation depend of the provider you use, please follow the appropriate guide :\n    - :simple-virtualbox: [Install with Virtualbox](../providers/virtualbox.md)\n    - :simple-vmware: [Install with VmWare](../providers/vmware.md)\n    - :simple-proxmox: [Install with Proxmox](../providers/proxmox.md)\n    - :material-microsoft-azure: [Install with Azure](../providers/azure.md)\n    - :simple-amazon: [Install with Aws](../providers/aws.md)\n    - 🏟️ [Install with Ludus](../providers/ludus.md)\n\n## TLDR - quick install\n\n??? info \"TLDR : :material-ubuntu: ubuntu 22.04 quick install\"\n\n    ```bash\n    # Install vbox\n    sudo apt install virtualbox\n\n    # Install vagrant\n    wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg\n    echo \"deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main\" | sudo tee /etc/apt/sources.list.d/hashicorp.list\n    sudo apt update && sudo apt install vagrant\n\n    # Install Vagrant plugins\n    vagrant plugin install vagrant-reload vagrant-vbguest winrm winrm-fs winrm-elevated\n    \n    # Add some dependencies\n    sudo apt install sshpass lftp rsync openssh-client python3.10-venv\n\n    git clone https://github.com/Orange-Cyberdefense/GOAD.git\n    cd GOAD\n    # verify installation\n    ./goad.sh -t check -l GOAD -p virtualbox\n\n    # install\n    ./goad.sh -t install -l GOAD -p virtualbox\n\n    # launch goad in interactive mode\n    ./goad.sh\n    ```\n\n## Installation\n\n- Installation is in three parts :\n    - Templating : this will create the template to use (needed only for proxmox and ludus)\n    - Providing : this will instantiate the virtual machines depending on your provider\n    - Provisioning : it is always made with ansible, it will install all the stuff to create the lab\n\n- GOAD script cover the providing and provisioning part\n\n- The install script take multiple parameters:\n    - `-p`  : the provider to use (vmware/virtualbox/proxmox/ludus/azure/aws)\n    - `-l`  : the lab to install (GOAD/GOAD-Light/SCCM/NHA/MINILAB)\n    - `-m`  : the method of installation (local/runner/docker/remote), most of the time don't change it\n    - `-ip` : the ip range to use\n\n- The easy way is just launch `./goad.sh` and use help `?`in the interactive prompt\n\n\n### Python Dependencies\n\n- Goad in :simple-python: python come with a lot of dependencies as you can see in the `requirements.yml` file on the root of the project.\n- If you don't want to run the provisioning from your python venv but only from docker you can use `goad_docker.sh` script instead of `goad.sh`. This will run the ansible with the docker method instead of local or runner.\n\nThis are the python dependencies used by goad :\n\n- Mandatory for :simple-python: goad.py:\n```\nrich\npsutil\nJinja2\npyyaml\n```\n\n- Mandatory for :material-ansible: ansible inside goad (for provisioning method local or runner) :\n  - python < 3.11\n    ```\n    # Ansible\n    ansible_runner\n    ansible-core==2.12.6\n    pywinrm\n    ```\n  - python >= 3.11\n    ```\n    # Ansible\n    setuptools\n    ansible_runner\n    ansible-core==2.18.0\n    pywinrm\n    ```\n\n- Mandatory for :material-microsoft-azure: azure provider :\n```\n# AZURE\nazure-identity\nazure-mgmt-compute\nazure-mgmt-network\n```\n\n- Mandatory for :simple-amazon: aws provider :\n```\n# AWS\nboto3\n```\n\n- Mandatory for :simple-proxmox: proxmox provider:\n```\n# Proxmox\nproxmoxer\nrequests\n```\n\n- You can launch goad without installing all the pip package but for that you will have to disable some dependencies with the `-d` arguments:\n```\n-d vmware     : disable vmware provider\n-d virtualbox : disable virtualbox provider\n-d azure      : disable azure provider\n-d aws        : disable azure provider\n-d proxmox    : disable proxmox provider\n-d ludus      : disable ludus provider\n-d local      : disable local provisioning method (if you use docker only)\n-d runner     : disable ansible runner provisioning method (if you use docker only)\n-d remote     : disable remote provisioning method\n-d docker     : disable docker provisioning method\n```\n\n## Configuration files\n\n### $HOME/.goad/goad.ini\n\n- On the first launch goad create a global configuration file at : `$HOME/.goad/goad.ini` this file contains some default configuration and some parameters needed by some providers.\n\n- If you change the `[default]` config it will change the default selection when goad start\n- Others configurations are related to specific providers\n\n```\n[default]\n; lab: goad / goad-light / minilab / nha / sccm\nlab = GOAD\n; provider : virtualbox / vmware / aws / azure / proxmox\nprovider = vmware\n; provisioner method : local / remote\nprovisioner = local\n; ip_range (3 first ip digits)\nip_range = 192.168.56\n\n[aws]\naws_region = eu-west-3\naws_zone = eu-west-3c\n\n[azure]\naz_location = westeurope\n\n[proxmox]\npm_api_url = https://192.168.1.1:8006/api2/json\npm_user = infra_as_code@pve\npm_node = GOAD\npm_pool = GOAD\npm_full_clone = false\npm_storage = local\npm_vlan = 10\npm_network_bridge = vmbr3\npm_network_model = e1000\n\n[proxmox_templates_id]\nwinserver2019_x64 = 102\nwinserver2016_x64 = 103\nwinserver2019_x64_utd = 104\nwindows10_22h2_x64 = 105\n\n[ludus]\n; api key must not have % if you have a % in it, change it by a %%\nludus_api_key = change_me\nuse_impersonation = yes\n```\n\n### Global configuration : globalsettings.ini\n\n- Goad got a global configuration file : `globalsettings.ini` used by the ansible provisioning\n- This file is an ansible inventory file.\n- This file is always added at the end of the ansible inventory file list so you can override values here\n- You can change it before running the installation to modify :\n    - keyboard_layouts\n    - proxy configuration\n    - add a route to the vm\n    - change the default dns_forwarder\n    - disable ssl for winrm communication\n"
  },
  {
    "path": "docs/mkdocs/docs/installation/linux.md",
    "content": "# :material-linux: Linux\n\n- First you will prepare your host for an hypervisor\n- Second you will prepare your python environment\n\n## Prepare your Provider\n\n=== \":simple-virtualbox: Virtualbox\"\n\n    - Vagrant\n        - In order to download vm and create them on virtualbox you need to install vagrant\n        - [https://developer.hashicorp.com/vagrant/install#linux](https://developer.hashicorp.com/vagrant/install#linux)\n    \n    - Virtualbox\n        - Install virtualbox\n        ```bash\n        sudo apt install virtualbox\n        ```\n\n    - Install vagrant plugins\n    ```bash\n    vagrant plugin install vagrant-reload vagrant-vbguest winrm winrm-fs winrm-elevated\n    ```\n\n    !!! warning \"Disk space\"\n        The lab takes about 77GB (but you have to get the space for the vms vagrant images windows server 2016 (22GB) / windows server 2019 (14GB) / ubuntu 18.04 (502M))\n        The total space needed for the lab is ~115 GB (depend on the lab you use and it will take more space if you take snapshots), be sure you have enough disk space before install.\n\n    !!! warning \"RAM\"\n        Depending on the lab you will need a lot of ram to run all the virtual machines. Be sure to have at least 20GB for GOAD-Light and 24GB for GOAD.\n\n=== \":simple-vmware: Vmware workstation\"\n\n    !!! tip\n        Vmware workstation is now free for personal use !\n\n    - Vagrant\n        - In order to download vm and create them on virtualbox you need to install vagrant\n        - [https://developer.hashicorp.com/vagrant/install#linux](https://developer.hashicorp.com/vagrant/install#linux)\n    \n    - Vmware workstation\n        - Install vmware workstation [https://support.broadcom.com/group/ecx/productdownloads?subfamily=VMware+Workstation+Pro](https://support.broadcom.com/group/ecx/productdownloads?subfamily=VMware+Workstation+Pro)\n\n    - Install vagrant vmware utility : [https://developer.hashicorp.com/vagrant/install/vmware](https://developer.hashicorp.com/vagrant/install/vmware#linux)\n\n    - Install the following vagrant plugins:\n        ```\n        vagrant plugin install vagrant-reload vagrant-vmware-desktop winrm winrm-fs winrm-elevated\n        ```\n\n    !!! warning \"Disk space\"\n        The lab takes about 77GB (but you have to get the space for the vms vagrant images windows server 2016 (22GB) / windows server 2019 (14GB) / ubuntu 18.04 (502M))\n        The total space needed for the lab is ~115 GB (depend on the lab you use and it will take more space if you take snapshots), be sure you have enough disk space before install.\n\n    !!! warning \"RAM\"\n        Depending on the lab you will need a lot of ram to run all the virtual machines. Be sure to have at least 20GB for GOAD-Light and 24GB for GOAD.\n\n=== \":material-microsoft-azure: Azure\"\n    - Azure CLI\n        - Install azure cli\n            [https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots)\n        - Connect to azure :\n            ```bash\n            az login\n            ```\n    - Terraform\n        - The installation to Azure use terraform so you will have to install it: [https://developer.hashicorp.com/terraform/install](https://developer.hashicorp.com/terraform/install)\n\n\n=== \":simple-amazon: Aws\"\n    - AWS CLI\n\n        - Install aws cli \n            [https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html#getting-started-install-instructions](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html#getting-started-install-instructions)\n        - Create an aws access key and secret for goad usage\n            - Go to IAM > User > your user > Security credentials\n            - Click the Create access key button\n            - Create a group \"[goad]\" in credentials file ~/.aws/credentials\n                ```\n                [goad]\n                aws_access_key_id = changeme\n                aws_secret_access_key = changeme\n                ```\n            - Be sure to chmod 400 the file\n\n            !!! warning \"credentials in plain text\"\n                Storing credentials in plain text is always a bad idea, but aws cli work like that be sure to restrain the right access to this file\n\n    - Terraform\n        - The installation to Aws use terraform so you will have to install it: [https://developer.hashicorp.com/terraform/install](https://developer.hashicorp.com/terraform/install)\n\n=== \":simple-proxmox: Proxmox\"\n\n    - Proxmox install is very complex and use a lot of steps\n    - A complete guide to proxmox installation is available here : [https://mayfly277.github.io/categories/proxmox/](https://mayfly277.github.io/categories/proxmox/)\n\n=== \"🏟️  Ludus\"\n\n    - To add GOAD on Ludus please use goad directly on the server.\n    - By now goad can work only directly on the server and not from a workstation client.\n\n    - Install Ludus : [https://docs.ludus.cloud/docs/quick-start/install-ludus/](https://docs.ludus.cloud/docs/quick-start/install-ludus/)\n\n    - Be sure to create an administrator user and keep his api key\n\n    - Once your installation is complete on ludus server (debian 12) and your user is created do :\n    \n    ```bash\n    git clone https://github.com/Orange-Cyberdefense/GOAD.git\n    cd GOAD\n    sudo apt install python3.11-venv\n    ./goad.sh\n    ...>exit\n    vim ~/.goad/goad.ini # add the api_key in the config file (keep impersonate to yes and use an admin user)\n    ./goad.sh -p ludus\n    ...>set_lab XXX # GOAD/GOAD-Light/NHA/SCCM\n    ...>install\n    ```\n\n## Prepare your python environment for goad.py\n\n=== \"Classic\"\n    \n    - To run the Goad installation/management script you will need : **Python version >=3.8** with venv module installed\n    \n    - Install the python3-venv corresponding to your python version \n    \n    ```bash\n    sudo apt install python<version>-venv\n    ```\n    \n    - Example:\n    \n    ```bash\n    sudo apt install python3.10-venv\n    ```\n\n    - Then you are ready to launch \n\n    ```\n    ./goad.sh\n    ```\n\n    - The script will :\n        - verify python version >=3.8\n        - create a venv in `~/.goad/.venv`\n        - launch python requirements installation\n        - launch ansible-galaxy collections requirements installation\n        - start goad.py with the venv created\n\n    !!! tip\n        if you got an error during requirements installation, look at the error and delete `~/.goad/.venv` before try again\n\n    !!! tip\n        if you need to force a python version change the variable `py=python3` to `py=python3.10` for example in the `goad.sh` script\n\n=== \"With poetry\"\n\n    - Install python dependencies:\n    ```\n    poetry install\n    ``` \n\n    - Install ansible-galaxy requirements:\n        - If python < 3.11\n        ```\n        poetry run ansible-galaxy ansible/requirements.yml\n        ```\n\n        - If python >= 3.11\n        ```\n        poetry run ansible-galaxy ansible/requirements_311.yml\n        ```\n\n    - Run goad:\n    ```\n    poetry run python3 goad.py\n    ```\n\n=== \"Provisioning with docker\"\n    \n    !!! info\n        With this method ansible-core will not be installed locally on your venv\n    \n    - [x] be sure you have docker installed on your os for the provisioning part (ansible will be run from the container)\n    - [x] To run the Goad installation/management script you will need :\n        -  Python (version >= 3.8) with venv module installed\n    \n    - Install the python3-venv corresponding to your python version \n    \n    ```bash\n    sudo apt install python<version>-venv\n    ```\n    \n    - Example:\n    \n    ```bash\n    sudo apt install python3.10-venv\n    ```\n    \n    - Run goad with `./goad_docker.sh` instead of `./goad.sh` to install the dependencies without the ansible part (local and runner provisioning method will not be available)"
  },
  {
    "path": "docs/mkdocs/docs/installation/windows.md",
    "content": "# :material-microsoft-windows: Windows\n\n- First you will prepare your windows host for an hypervisor\n- Second you will choose between \n    - install debian 12 with WSL to run goad install script\n    - Or prepare your windows host (install with a provisioning machine)\n\n## Prepare Windows Host\n\n=== \":simple-virtualbox: Virtualbox\"\n    If you want to use virtualbox as a hypervisor to create your vm.\n\n    - VAGRANT\n\n        If you want to create the lab on your windows computer you will need vagrant. Vagrant will be responsible to automate the process of vm download and creation.\n\n        - Download and install visual c++ 2019   : [https://aka.ms/vs/17/release/vc_redist.x64.exe](https://aka.ms/vs/17/release/vc_redist.x64.exe)\n        - Install vagrant : [https://developer.hashicorp.com/vagrant/install](https://developer.hashicorp.com/vagrant/install)\n\n    - Virtualbox\n\n        - Install virtualbox <= 7.1.x (vagrant supports up to vbox7.1.x at the time of writing) : [https://www.virtualbox.org/wiki/Downloads](https://www.virtualbox.org/wiki/Downloads)\n\n        - Install the following vagrant plugins:\n\n        ```\n        vagrant.exe plugin install vagrant-reload vagrant-vbguest winrm winrm-fs winrm-elevated\n        ```\n\n    !!! warning \"Disk space\"\n        The lab takes about 77GB (but you have to get the space for the vms vagrant images windows server 2016 (22GB) / windows server 2019 (14GB) / ubuntu 18.04 (502M))\n        The total space needed for the lab is ~115 GB (depend on the lab you use and it will take more space if you take snapshots), be sure you have enough disk space before install.\n\n    !!! warning \"RAM\"\n        Depending on the lab you will need a lot of ram to run all the virtual machines. Be sure to have at least 20GB for GOAD-Light and 24GB for GOAD.\n\n=== \":simple-vmware: Vmware Workstation\"\n\n    If you want to use vmware workstation as an hypervisor to create your vm.\n\n    !!! tip\n        Vmware workstation is now free for personal use !\n\n    - VAGRANT\n\n        If you want to create the lab on your windows computer you will need vagrant. Vagrant will be responsible to automate the process of vm download and creation.\n\n        - Download and install visual c++ 2019   : [https://aka.ms/vs/17/release/vc_redist.x64.exe](https://aka.ms/vs/17/release/vc_redist.x64.exe)\n        - Install vagrant : [https://developer.hashicorp.com/vagrant/install](https://developer.hashicorp.com/vagrant/install)\n\n    - Vmware Workstation\n        - Install vmware workstation : [https://support.broadcom.com/group/ecx/productdownloads?subfamily=VMware+Workstation+Pro](https://support.broadcom.com/group/ecx/productdownloads?subfamily=VMware+Workstation+Pro)\n\n        !!! bug \"vmware workstation install bug\"\n            if you got an error about groups and permission during vmware workstation install consider running this in an administrator cmd prompt:\n            ```\n            net localgroup /add \"Users\"\n            net localgroup /add \"Authenticated Users\"\n            ```\n\n        - Install vagrant vmware utility : [https://developer.hashicorp.com/vagrant/install/vmware](https://developer.hashicorp.com/vagrant/install/vmware)\n\n        - Install the following vagrant plugins:\n\n        ```\n        vagrant.exe plugin install vagrant-reload vagrant-vmware-desktop winrm winrm-fs winrm-elevated\n        ```\n\n    !!! warning \"Disk space\"\n        The lab takes about 77GB (but you have to get the space for the vms vagrant images windows server 2016 (22GB) / windows server 2019 (14GB) / ubuntu 18.04 (502M))\n        The total space needed for the lab is ~115 GB (depend on the lab you use and it will take more space if you take snapshots), be sure you have enough disk space before install.\n\n    !!! warning \"RAM\"\n        Depending on the lab you will need a lot of ram to run all the virtual machines. Be sure to have at least 20GB for GOAD-Light and 24GB for GOAD.\n\n\n=== \":simple-amazon: Aws\"\n    Nothing to prepare on windows host, install and prepare wsl and next follow linux install from your wsl console : [see aws linux install](linux.md/#__tabbed_1_4)\n\n=== \":material-microsoft-azure: Azure\"\n    Nothing to prepare on windows host, install and prepare wsl and next linux install from your wsl console [see azure linux install](linux.md/#__tabbed_1_3)\n\n=== \":simple-proxmox: Promox\"\n    Not supported, you will have to create a provisioning machine on your proxmox and run goad from then ([see proxmox linux install](linux.md/#__tabbed_1_5))\n\n=== \"🏟️  Ludus\"\n    Not supported, you will have to act from your ludus server ([see ludus linux install](linux.md/#__tabbed_1_6))\n\n## :simple-python: Prepare python environment\n\n=== \"With WSL\"\n    Now your host environment is ready for virtual machine creation. Now we will install WSL to run the goad installation script.\n\n    !!! info \"wsl version\"\n        New Linux installations, installed using the wsl --install command, will be set to WSL 2 by default.\n        The wsl --set-version command can be used to downgrade from WSL 2 to WSL 1 or to update previously installed Linux distributions from WSL 1 to WSL 2.\n        To see whether your Linux distribution is set to WSL 1 or WSL 2, use the command: `wsl -l -v`.\n        To change versions, use the command: `wsl --set-version <distro name> <wsl_version>` replacing <distro name> with the name of the Linux distribution that you want to update. \n        As an example: `wsl --set-version Debian 1` will set your Debian distribution to use WSL 1.\n\n    !!! tip \"use wsl version1\"\n        by now wsl was tested succefully with version 1 \n\n    ### Install WSL\n\n    - First install wsl on your environment [https://learn.microsoft.com/en-us/windows/wsl/install](https://learn.microsoft.com/en-us/windows/wsl/install)\n    - Next go to the microsoft store and install debian (debian12)\n\n    ### Prepare WSL distribution\n    - Open debian console then :\n\n        - Verify you are using python version >= 3.8\n        ```bash\n        python3 --version\n        ```\n\n        - Install python packages\n        ```bash\n        sudo apt update\n        sudo apt install python3 python3-pip python3-venv libpython3-dev git\n        ```\n\n    - Next you can clone and run goad\n\n    ```bash\n    cd /mnt/c/whatever_folder_you_want      # This path HAS to be on one of your drives (C:/D:/E:/...)!\n    git clone https://github.com/Orange-Cyberdefense/GOAD.git\n    cd GOAD\n    ./goad.sh\n    ```\n\n=== \"With Python on windows host\"\n\n    !!! info \"For vmware or virtualbox only\"\n        This mode doesn't need WSL but it is only if you plan to install goad locally on vmware or virtualbox\n\n    - Prerequistes:\n        - :simple-python: [python](https://www.python.org/downloads/windows/) on your windows (tested ok with python 3.10) \n        - :simple-git: [git](https://git-scm.com/downloads/win)\n    \n    - Checkout GOAD : \n        ```\n        git clone https://github.com/Orange-Cyberdefense/GOAD\n        cd GOAD/\n        ```\n    - Install python dependencies (choose the noansible file) : \n        ```\n        python -m venv .env\n        source .env\\Scripts\\activate        # In CMD: .env\\Scripts\\activate.bat\n        pip install -r noansible_requirements.yml\n        ```\n    - Launch goad with vm provisioning method : \n        ```\n        py goad.py -m vm\n        ```\n"
  },
  {
    "path": "docs/mkdocs/docs/instances.md",
    "content": "# 🇮 instances\n\nWhen you create a lab, goad will create an instance folder.\nAll the instances are stored in the workspace/ folder inside goad.\n\n```\nworkspace/\n    .\n    ├── 6caf1a-goad-light-azure              # Instance ID\n    │   ├── exchange_inventory               # extension inventory\n    │   ├── instance.json                    # instance json file (name, status, etc..)\n    │   ├── inventory                        # provider inventory\n    │   ├── provider                         # provider folder\n    │   │   ├── jumpbox.tf\n    │   │   ├── linux.tf\n    │   │   ├── main.tf\n    │   │   ├── network.tf\n    │   │   ├── outputs.tf\n    │   │   ├── terraform.tfstate\n    │   │   ├── terraform.tfstate.backup\n    │   │   ├── variables.tf\n    │   │   └── windows.tf\n    │   └── ssh_keys                         # the keys generated by this instance\n    │       └── ubuntu-jumpbox.pem\n    ├── 7b12f1-goad-light-vmware             # another instance\n    │   ├── instance.json\n    │   ├── inventory\n    │   ├── inventory_disable_vagrant\n    │   ├── provider\n    │   │   └── Vagrantfile\n    │   └── ssh_keys\n```\n\n## instance creation\n\n- On instance folder creation (when you run `install` or `create_empty`), the provider files inside the template/<provider> folder are copied into the instance.\n- These files are merged with the datas inside `ad/<lab>/providers/<provider>/` folder and the datas inside `extensions/<extension>/providers/<provider>/`\n- The merged result is present in the `workspace/<instance_id>/provider/` folder and contain all the recipes to create the infrastructure\n\n- inventories files are also copied from `ad/<lab>/provider/<provider>/inventory` and `extensions/<extension>/inventory` (see [provisioning](provisioning.md) for more information in provisioning)"
  },
  {
    "path": "docs/mkdocs/docs/javascripts/extra.js",
    "content": "document.addEventListener(\"DOMContentLoaded\", function() {\n    load_navpane();\n});\n\nfunction load_navpane() {\n    var width = window.innerWidth;\n    if (width <= 1200) {\n        return;\n    }\n\n    var nav = document.getElementsByClassName(\"md-nav\");\n    for(var i = 0; i < nav.length; i++) {\n        if (typeof nav.item(i).style === \"undefined\") {\n            continue;\n        }\n\n        if (nav.item(i).getAttribute(\"data-md-level\") && nav.item(i).getAttribute(\"data-md-component\")) {\n            nav.item(i).style.display = 'block';\n            nav.item(i).style.overflow = 'visible';\n        }\n    }\n\n    var nav = document.getElementsByClassName(\"md-nav__toggle\");\n    for(var i = 0; i < nav.length; i++) {\n       nav.item(i).checked = true;\n    }\n}"
  },
  {
    "path": "docs/mkdocs/docs/labs/DRACARYS.md",
    "content": "# DRACARYS\n\n![DRACARYS](../img/dracarys_logo.png)\n\n- DRACARYS is written as a training challenge where GOAD was written as a lab with a maximum of vulns.\n- You should find your way in to get domain admin on the domain dracarys.lab\n- Using vagrant user is prohibited of course ^^\n- Starting point is on lx01 : `<ip_range>.12`\n- Obviously do not cheat by looking at the passwords and flags in the recipe files, the lab must start without user to full compromise. \n- If you use goad previously your ansible requirements may not be up to date. Be sure to do this before the install:\n\n```bash\nsource ~/.goad/.venv/bin/activate\ncd ~/GOAD/ansible\n\n# if you python is >=3.11\nansible-galaxy install -r requirements_311.yml \n# if you got a python <3.10\nansible-galaxy install -r requirements.yml \n```\n\n- Install :\n\n```bash\n./goad.sh -t install -l DRACARYS -p virtualbox\n```\n\nor\n\n```bash\n./goad.sh\n> set_lab DRACARYS\n> set_provider <your_provider>\n> set_iprange 192.168.56  # select the one you want and you can skip this with ludus\n> install\n```\n\n- Once install finish disable vagrant user to avoid using it :\n\n```bash\n./goad.sh\n> load <instance_id>\n> disable_vagrant\n```\n\n- Now do a reboot of all the machine to avoid unintended secrets stored : \n\n```bash\n> stop\n> start\n```\n\nAnd you are ready to play ! :)\n\n- If you need to re-enable vagrant\n\n```bash\n> load <instance_id>\n> enable_vagrant\n```\n\n- If you want to create a write up of the chall, no problem, have fun. Please ping me on X (@M4yFly) or Discord, i will be happy to read it :)\n\n!!! tip\n    Be sure to get your arsenal up to date\n"
  },
  {
    "path": "docs/mkdocs/docs/labs/GOAD-Light.md",
    "content": "# GOAD-Light\n\nThis is a light version of goad without the essos domain. This lab was build for computer with less performance (min ~20GB).\n\n![GOAD Light overview](../img/GOAD-Light_schema.png)\n\nMissing scenarios:\n\n- cross forest exploitation (no more external forest)\n- mssql trusted link\n- some old computer vulnerabilities (zero logon, petitpotam unauthent,...)\n- ESC4, ESC2/3\n\n## Servers\nThis lab is actually composed of five virtual machines:\n\n**domain : sevenkingdoms.local**\n\n- **kingslanding** : DC01  running on Windows Server 2019 (with windefender enabled by default)\n\n**domain : north.sevenkingdoms.local**\n\n- **winterfell**   : DC02  running on Windows Server 2019 (with windefender enabled by default)\n- **castelblack**  : SRV02 running on Windows Server 2019 (with windefender **disabled** by default)\n\n\n## Users/Groups and associated vulnerabilites/scenarios\n\n- You can find a lot of the available scenarios on [https://mayfly277.github.io/categories/ad/](https://mayfly277.github.io/categories/goad/)\n\n**NORTH.SEVENKINGDOMS.LOCAL**\n\n- STARKS:              RDP on WINTERFELL AND CASTELBLACK\n    - arya.stark:        Execute as user on mssql\n    - eddard.stark:      DOMAIN ADMIN NORTH/ (bot 5min) LLMRN request to do NTLM relay with responder\n    - catelyn.stark:     \n    - robb.stark:        bot (3min) RESPONDER LLMR\n    - sansa.stark:       \n    - brandon.stark:     ASREP_ROASTING\n    - rickon.stark:      \n    - theon.greyjoy:\n    - jon.snow:          mssql admin / KERBEROASTING / group cross domain / mssql trusted link\n    - hodor:             PASSWORD SPRAY (user=password)\n- NIGHT WATCH:         RDP on CASTELBLACK\n    - samwell.tarly:     Password in ldap description / mssql execute as login\n                        GPO abuse (Edit Settings on \"STARKWALLPAPER\" GPO)\n    - jon.snow:          (see starks)\n    - jeor.mormont:      (see mormont)\n- MORMONT:             RDP on CASTELBLACK\n    - jeor.mormont:      ACL writedacl-writeowner on group Night Watch\n- AcrossTheSea :       cross forest group\n\n**SEVENKINGDOMS.LOCAL**\n\n- LANISTERS\n    - tywin.lannister:   ACL forcechangepassword on jaime.lanister\n    - jaime.lannister:   ACL genericwrite-on-user joffrey.baratheon\n    - tyron.lannister:   ACL self-self-membership-on-group Small Council\n    - cersei.lannister:  DOMAIN ADMIN SEVENKINGDOMS\n- BARATHEON:           RDP on KINGSLANDING\n    - robert.baratheon:  DOMAIN ADMIN SEVENKINGDOMS\n    - joffrey.baratheon: ACL Write DACL on tyron.lannister\n    - renly.baratheon:\n    - stannis.baratheon: ACL genericall-on-computer kingslanding / ACL writeproperty-self-membership Domain Admins\n- SMALL COUNCIL :      ACL add Member to group dragon stone / RDP on KINGSLANDING\n    - petyer.baelish:    ACL writeproperty-on-group Domain Admins\n    - lord.varys:        ACL genericall-on-group Domain Admins / Acrossthenarrossea\n    - maester.pycelle:   ACL write owner on group Domain Admins\n- DRAGONSTONE :        ACL Write Owner on KINGSGUARD\n- KINGSGUARD :         ACL generic all on user stannis.baratheon\n- AccorsTheNarrowSea:       cross forest group\n\n\n## Computers Users and group permissions\n\n- SEVENKINGDOMS\n    - DC01 : kingslanding.sevenkingdoms.local (Windows Server 2019) (SEVENKINGDOMS DC)\n        - Admins : robert.baratheon (U), cersei.lannister (U)\n        - RDP: Small Council (G)\n\n- NORTH\n    - DC02 : winterfell.north.sevenkingdoms.local (Windows Server 2019) (NORTH DC)\n        - Admins : eddard.stark (U), catelyn.stark (U), robb.stark (U)\n        - RDP: Stark(G)\n\n    - SRV02 : castelblack.essos.local (Windows Server 2019) (IIS, MSSQL, SMB share)\n        - Admins: jeor.mormont (U)\n        - RDP: Night Watch (G), Mormont (G), Stark (G)\n        - IIS : allow asp upload, run as NT Authority/network\n        - MSSQL:\n            - admin : jon.snow\n            - impersonate : \n                - execute as login : samwel.tarlly -> sa\n                - execute as user : arya.stark -> dbo\n"
  },
  {
    "path": "docs/mkdocs/docs/labs/GOAD-Mini.md",
    "content": "# GOAD-Mini\n\nThis is a minimalist version of goad with only sevenkingdoms.lab domain. This lab was build for a minimalist base to do test and try extensions.\n\n![goad_mini.png](../img/goad_mini.png)\n\n## Servers\n**domain : sevenkingdoms.local**\n- **kingslanding** : DC01  running on Windows Server 2019 (with windefender enabled by default)\n\n## Users/Groups and associated vulnerabilites/scenarios\n\n**SEVENKINGDOMS.LOCAL**\n\n- LANISTERS\n    - tywin.lannister:   ACL forcechangepassword on jaime.lanister\n    - jaime.lannister:   ACL genericwrite-on-user joffrey.baratheon\n    - tyron.lannister:   ACL self-self-membership-on-group Small Council\n    - cersei.lannister:  DOMAIN ADMIN SEVENKINGDOMS\n- BARATHEON:           RDP on KINGSLANDING\n    - robert.baratheon:  DOMAIN ADMIN SEVENKINGDOMS\n    - joffrey.baratheon: ACL Write DACL on tyron.lannister\n    - renly.baratheon:\n    - stannis.baratheon: ACL genericall-on-computer kingslanding / ACL writeproperty-self-membership Domain Admins\n- SMALL COUNCIL :      ACL add Member to group dragon stone / RDP on KINGSLANDING\n    - petyer.baelish:    ACL writeproperty-on-group Domain Admins\n    - lord.varys:        ACL genericall-on-group Domain Admins / Acrossthenarrossea\n    - maester.pycelle:   ACL write owner on group Domain Admins\n- DRAGONSTONE :        ACL Write Owner on KINGSGUARD\n- KINGSGUARD :         ACL generic all on user stannis.baratheon\n- AccorsTheNarrowSea:       cross forest group\n\n\n## Computers Users and group permissions\n\n- SEVENKINGDOMS\n    - DC01 : kingslanding.sevenkingdoms.local (Windows Server 2019) (SEVENKINGDOMS DC)\n        - Admins : robert.baratheon (U), cersei.lannister (U)\n        - RDP: Small Council (G)\n"
  },
  {
    "path": "docs/mkdocs/docs/labs/GOAD.md",
    "content": "# GOAD\n\nGOAD is the first and main lab of this project. It contains 3 domains and 2 forest.\n\n![GOAD overview](../img/GOAD_schema.png)\n\n## Servers\n\nThis lab is actually composed of five virtual machines:\n\n**domain sevenkingdoms.local**\n\n- **kingslanding** : DC01  running on Windows Server 2019 (with windefender enabled by default)\n\n**domain north.sevenkingdoms.local**\n\n- **winterfell**   : DC02  running on Windows Server 2019 (with windefender enabled by default)\n- **castelblack**  : SRV02 running on Windows Server 2019 (with windefender **disabled** by default)\n\n**domain essos.local**\n\n- **meereen**      : DC03  running on Windows Server 2016 (with windefender enabled by default)\n- **braavos**      : SRV03 running on Windows Server 2016 (with windefender enabled by default)\n\n\n## WRITEUP\n\n- All the writeups of the Game Of Active Directory lab are available on mayfly's blog : [https://mayfly277.github.io/categories/goad/](https://mayfly277.github.io/categories/goad/)\n\n\n## Computers Users and group permissions\n\n- **SEVENKINGDOMS / sevenkingdoms.local**\n    - DC01 : kingslanding.sevenkingdoms.local (Windows Server 2019) (SEVENKINGDOMS DC)\n        - Admins : robert.baratheon (U), cersei.lannister (U)\n        - RDP: Small Council (G)\n\n- **NORTH / north.sevenkingdoms.local**\n    - DC02 : winterfell.north.sevenkingdoms.local (Windows Server 2019) (NORTH DC)\n        - Admins : eddard.stark (U), catelyn.stark (U), robb.stark (U)\n        - RDP: Stark(G)\n\n    - SRV02 : castelblack.essos.local (Windows Server 2019) (IIS, MSSQL, SMB share)\n        - Admins: jeor.mormont (U)\n        - RDP: Night Watch (G), Mormont (G), Stark (G)\n        - IIS : allow asp upload, run as NT Authority/network\n        - MSSQL:\n            - admin : jon.snow\n            - impersonate : \n                - execute as login : samwel.tarlly -> sa\n                - execute as user : arya.stark -> dbo\n            - link :\n                - to braavos : jon.snow -> sa\n\n- **ESSOS / essos.local**\n    - DC03  : meereen.essos.local (Windows Server 2016) (ESSOS DC)\n        - Admins: daenerys.targaryen (U)\n        - RDP: Targaryen (G)\n\n    - SRV03 : braavos.essos.local (Windows Server 2016) (MSSQL, SMB share)\n        - Admins: khal.drogo (U)\n        - RDP: Dothraki (G)\n        - MSSQL :\n            - admin : khal.drogo\n            - impersonate :\n                - execute as login : jorah.mormont -> sa\n            - link:\n                - to castelblack: jorah.mormont -> sa\n\n## Users/Groups and associated scenarios\n\n- Graph of some scenarios is available here :\n![diagram-GOAD_compromission_Path_dark](./../img/diagram-GOAD_compromission_Path_dark.png)\n\nNORTH.SEVENKINGDOMS.LOCAL\n\n- STARKS:              RDP on WINTERFELL AND CASTELBLACK\n    - arya.stark:        Execute as user on mssql, pass on all share\n    - eddard.stark:      DOMAIN ADMIN NORTH/ (bot 5min) LLMRN request to do NTLM relay with responder\n    - catelyn.stark:     \n    - robb.stark:        bot (3min) RESPONDER LLMR / lsass present user\n    - sansa.stark:       keywalking password / unconstrained delegation\n    - brandon.stark:     ASREP_ROASTING\n    - rickon.stark:      pass spray WinterYYYY\n    - jon.snow:          mssql admin / KERBEROASTING / mssql trusted link\n    - hodor:             PASSWORD SPRAY (user=password)\n- NIGHT WATCH:         RDP on CASTELBLACK\n    - samwell.tarly:     Password in ldap description / mssql execute as login\n                        GPO abuse (Edit Settings on \"STARKWALLPAPER\" GPO)\n    - jon.snow:          (see starks)\n    - jeor.mormont:      (see mormont)\n- MORMONT:             RDP on CASTELBLACK\n     - jeor.mormont:      Admin castelblack, pass in sysvol script\n- AcrossTheSea :       cross forest group\n\nSEVENKINGDOMS.LOCAL\n\n- LANISTERS\n    - tywin.lannister:   ACE forcechangepassword on jaime.lanister, password on sysvol cyphered\n    - jaime.lannister:   ACE genericwrite-on-user joffrey.baratheon\n    - tyron.lannister:   ACE self membership on small council\n    - cersei.lannister:  DOMAIN ADMIN SEVENKINGDOMS\n- BARATHEON:           RDP on KINGSLANDING\n    - robert.baratheon:  DOMAIN ADMIN SEVENKINGDOMS, protected user\n    - joffrey.baratheon: ACE Write DACL on tyron.lannister\n    - renly.baratheon:   WriteDACL on container, sensitive user\n    - stannis.baratheon: ACE genericall-on-computer kingslanding \n- SMALL COUNCIL :      ACE add Member to group dragon stone / RDP on KINGSLANDING\n    - petyer.baelish:    \n    - lord.varys:        ACE genericall-on-group Domain Admins and sdholder\n    - maester.pycelle:   \n- DRAGONSTONE :        ACE Write Owner on group KINGSGUARD\n- KINGSGUARD :         ACE generic all on user stannis.baratheon\n- AccorsTheNarrowSea:       cross forest group\n\nESSOS.LOCAL\n\n- TARGERYEN\n    - missande :          ASREP roasting, generic all on khal\n    - daenerys.targaryen: DOMAIN ADMIN ESSOS\n    - viserys.targaryen:  ACE write property on jorah.mormont\n    - jorah.mormont:      mssql execute as login / mssql trusted link / Read LAPS Password\n- DOTHRAKI\n    - khal.drogo:         mssql admin / GenericAll on viserys (shadow credentials) / GenericAll on ECS4\n- DragonsFriends:       cross forest group\n- Spys:                 cross forest group / Read LAPS password  / ACL generic all jorah.mormont\n\n"
  },
  {
    "path": "docs/mkdocs/docs/labs/MINILAB.md",
    "content": "# MINI lab\n\n- The MINI lab is just a sample presented during an Article on the MISC magazine.\n- This is just a simple basic LAB with one DC (windows server 2019) and one Workstation (windows 10)\n"
  },
  {
    "path": "docs/mkdocs/docs/labs/NHA.md",
    "content": "# NINJA HACKER ACADEMY\n\n![NHA](../img/logo_NHA.jpeg)\n\n- NINJA HACKER ACADEMY (NHA) is written as a training challenge where GOAD was written as a lab with a maximum of vulns.\n- You should find your way in to get domain admin on the 2 domains (academy.ninja.lan and ninja.hack)\n- Starting point is on srv01 : 192.168.58.21\n\n- Flags are disposed on each machine, try to grab all. Be careful all the machines are up to date with defender enabled.\n- Some exploits needs to modify path so this lab is not very multi-players compliant (unless you do it as a team ;))\n- Obviously do not cheat by looking at the passwords and flags in the recipe files, the lab must start without user to full compromise. \n\n- Install :\n\n```bash\n./goad.sh -t install -l NHA -p virtualbox\n```\n\nor\n\n```bash\n./goad.sh\n> set_lab NHA\n> set_provider <your_provider>\n> set_iprange 192.168.56  # select the one you want and you can skip this with ludus\n> install\n```\n\n- Once install finish disable vagrant user to avoid using it :\n\n```bash\n./goad.sh\n> load <instance_id>\n> disable_vagrant\n```\n\n- Now do a reboot of all the machine to avoid unintended secrets stored : \n\n```bash\n> stop\n> start\n```\n\nAnd you are ready to play ! :)\n\n- If you need to re-enable vagrant\n\n```bash\n> load <instance_id>\n> enable_vagrant\n```\n\n- If you want to create a write up of the chall, no problem, have fun. Please ping me on X (@M4yFly) or Discord, i will be happy to read it :)\n\n!!! tip\n    No bruteforce, if not in rockyou do not waste your time and your cpu/gpu cycle.\n"
  },
  {
    "path": "docs/mkdocs/docs/labs/SCCM.md",
    "content": "# SCCM lab\n\n!!! success \"Thanks!\"\n    Thanks a lot to my colleague Issam (@KenjiEndo15), who start the project and provide me a lot of ansible roles to start from !\n\n![SCCM overview](../img/SCCMLAB_overview.png)\n\n## Servers\n4 virtual machines with Windows Server 2019\n\n- **DC** :  Domain Controler \n- **MECM** : mecm primary site serer\n- **MSSQL** : mecm sql server\n- **CLIENT** : mecm client computer\n\nAll vms got defender activated\n\n## Prerequisites\n- The prerequisites for the lab are the same as GOAD lab (virtualbox/vmware, python, ansible,...)\n- The lab take 16GB for the vagrant image + 100GB for the 4 vms\n- The installation take environ 2,5 hours (with fiber connection)\n- The lab download multiple files during the install (windows iso, mecm installation package, mssql installation package, ...), be sure to have a good internet connection.\n\n## Writeup\n\n- A writeup on SCCM exploitation is available here : [https://mayfly277.github.io/categories/sccm/](https://mayfly277.github.io/categories/sccm/)\n\n## proxmox installation\n- In order to use the proxmox provider follow this :\n\n1) create a template with the windows_server2019_proxmox_cloudinit_uptodate.pkvars.hcl packer file (guide here: https://mayfly277.github.io/posts/GOAD-on-proxmox-part2-packer/) (note the id after the creation)\n\n2) create the variable file (ad/SCCM/providers/proxmox/terraform/variables.tf) by coping the template (ad/SCCM/providers/proxmox/terraform/variables.tf.template) and change the value according to your proxmox environnement\n\n3) on the provisioning computer :\n```bash\n./goad.sh -t check -l SCCM -p proxmox -m local\n./goad.sh -t install -l SCCM -p proxmox -m local\n```\n\n4) if something goes wrong (restart of the vms during install, etc...), you can rerun only ansible with -a\n```bash\n./goad.sh -t install -l SCCM -p proxmox -m local -a\n```"
  },
  {
    "path": "docs/mkdocs/docs/labs/index.md",
    "content": "# Labs\n\n- Practice lab(s) :\n    - GOAD familly :\n        - [GOAD](GOAD.md) : 5 vms, 2 forests, 3 domains (full goad lab)\n        - [GOAD-Light](GOAD-Light.md) : 3 vms, 1 forest, 2 domains (smaller goad lab for those with a smaller pc)\n        - [GOAD-Mini](GOAD-Mini.md) : 1 vm, 1 domains (only sevenkingdoms.local, minimalist lab)\n\n        ![GOADfull](../img/diagram-GOADv3-full.png)\n   \n    - [SCCM](SCCM.md) : 4 vms, 1 forest, 1 domain, with microsoft configuration manager installed\n    ![SCCM overview](../img/SCCMLAB_overview.png)\n\n- Challenge lab :\n    - [NHA](NHA.md) : A challenge with 5 vms and 2 domains. no schema provided, you will have to find out how break it.\n\n- POC lab :\n    - [MINILAB](MINILAB.md): 2 vms, 1 forest, 1 domain (basic lab with one DC (windows server 2019) and one Workstation (windows 10))\n"
  },
  {
    "path": "docs/mkdocs/docs/packer/packer.md",
    "content": ""
  },
  {
    "path": "docs/mkdocs/docs/providers/aws.md",
    "content": "# :simple-amazon: Aws\n\n!!! success \"Thanks!\"\n    Thx to @ArnC_CarN for the initial work on the aws provider\n\n<div align=\"center\">\n  <img alt=\"terraform\" width=\"167\" height=\"150\" src=\"./../img/icon_terraform.png\">\n  <img alt=\"icon_aws\" width=\"193\"  height=\"150\" src=\"./../img/icon_aws.png\">\n  <img alt=\"icon_ansible\" width=\"150\"  height=\"150\" src=\"./../img/icon_ansible.png\">\n</div>\n\nThe architecture is quite the same than the Azure deployment.\n\n![Architecture](../img/aws_schema.png)\n\n!!! Warning\n    LLMNR, NBTNS and other poisoning network attacks will not work in aws environment.\n    Only network coerce attacks will work.\n\n## Prerequisites\n\n- [Terraform](https://www.terraform.io/downloads.html)\n- [AWS CLI](https://aws.amazon.com/cli/?nc1=h_ls)\n\n## AWS configuration\n\nYou need to configre AWS cli. Use a key with enough privileges on the tenant.\n\n```bash\naws configure\n```\n\n- Create an aws access key and secret for goad usage\n    - Go to IAM > User > your user > Security credentials\n    - Click the Create access key button\n    - Create a group \"[goad]\" in credentials file ~/.aws/credentials\n        ```\n        [goad]\n        aws_access_key_id = changeme\n        aws_secret_access_key = changeme\n        ```\n    - Be sure to chmod 400 the file\n\n    !!! warning \"credentials in plain text\"\n        Storing credentials in plain text is always a bad idea, but aws cli work like that be sure to restrain the right access to this file\n\n## Goad configuration\n\n- The goad configuration file as some options for aws:\n\n```\n# ~/.goad/goad.ini\n...\n[aws]\naws_region = eu-west-3\naws_zone = eu-west-3c\n```\n\n- If you want to use a different region and zone you can modify it (but this could break ami values in terraform)\n\n## Change AMI value\n\n- You can get the ami of Windows_Server with a query like that:\n```\naws ec2 describe-images \\\n  --region eu-west-3 \\\n  --owners 801119661308 \\\n  --filters \"Name=name,Values=Windows_Server-2016-English-Full-Base*\" \\\n  --query 'Images[*].[ImageId,Name,CreationDate]' \\\n  --output table\n```\n\n- for ubuntu use this command :\n```\naws ec2 describe-images \\\n  --region eu-west-3 \\\n  --owners 099720109477 \\\n  --filters \"Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*\" \\\n  --query \"Images[*].[ImageId,Name,CreationDate]\" \\\n  --output table\n```\n\n## Installation\n\n```bash\n# check prerequisites\n./goad.sh -t check -l GOAD -p aws\n# Install\n./goad.sh -t install -l GOAD -p aws\n```\n\nor from the interactive console :\n\n```bash\nGOAD/aws/remote/192.168.56.X > install\n```\n\n## start/stop/status\n\n- You can see the status of the lab with the command `status`\n- You can also start and stop the lab with the command `start` and `stop`\n\n\n## VMs ami\n\n- The vm used for goad are defined in the lab terraform file : `ad/<lab>/providers/aws/windows.tf`\n- This file is containing information about each vm in use\n\n```\n\"dc01\" = {\n  name               = \"dc01\"\n  domain             = \"sevenkingdoms.local\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-018ebfbd6b0a4c605\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCT-DJjgScp\"\n}\n```\n\n## How it works ?\n\n- On the installation goad script will create a folder into `goad/workspaces/<instance_folder>`\n- This folder will contain the terraform scripts and some of the ansible inventories\n- Goad will create the cloud infrastructure with terraform.\n- The lab is created (not provisioned yet) and a \"jumpbox\" vm is also created\n- Next the needed sources will be pushed to the jumpbox using `ssh` and `rsync`\n- The jumpbox ssh_key is stored on `goad/workspaces/<instance_folder>/ssh_keys`\n- The jumpbox is prepared to run ansible\n- The provisioning is launch with ssh remotely on the jumpbox\n\n## Install step by step\n\n```bash\nGOAD/aws/remote/192.168.56.X > create_empty # create empty instance\nGOAD/aws/remote/192.168.56.X > load <instance_id>\nGOAD/aws/remote/192.168.56.X (<instance_id>) > provide # play terraform\nGOAD/aws/remote/192.168.56.X (<instance_id>) > sync_source_jumpbox # sync jumpbox source\nGOAD/aws/remote/192.168.56.X (<instance_id>) > prepare_jumpbox # install dependencies on jumpbox\nGOAD/aws/remote/192.168.56.X (<instance_id>) > provision_lab # run ansible\n```\n\n## Tips\n\n- To connect to the jumpbox VM you can use `ssh_jumpbox` in the goad interactive console\n- To setup a socks proxy you can use `ssh_jumpbox_proxy <proxy_port>` in the goad interactive console\n- All aws elements are tagged with `<lab_name>-<lab_instance_id>`"
  },
  {
    "path": "docs/mkdocs/docs/providers/azure.md",
    "content": "# :material-microsoft-azure: Azure\n\n!!! success \"Thanks!\"\n    Thx to Julien Arault for the initial work on the azure provider\n\n\n<div align=\"center\">\n  <img alt=\"terraform\" width=\"167\" height=\"150\" src=\"./../img/icon_terraform.png\">\n  <img alt=\"icon_azure\" width=\"160\"  height=\"150\" src=\"./../img/icon_azure.png\">\n  <img alt=\"icon_ansible\" width=\"150\"  height=\"150\" src=\"./../img/icon_ansible.png\">\n</div>\n\n![Architecture](../img/azure_architecture.png)\n\n!!! Warning\n    LLMNR, NBTNS and other poisoning network attacks will not work in azure environment.\n    Only network coerce attacks will work.\n\n## Prerequisites\n\n- [Terraform](https://www.terraform.io/downloads.html)\n- [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)\n\n## Azure configuration\n\nYou need to login to Azure with the CLI.\n\n```bash\naz login\n```\n\n## Goad configuration\n\n- The goad configuration file as some options for azure:\n\n```\n# ~/.goad/goad.ini\n...\n[azure]\naz_location = westeurope\n```\n\n- If you want to use a different location you can modify it.\n\n\n## Installation\n\n```bash\n# check prerequisites\n./goad.sh -t check -l GOAD -p azure\n# Install\n./goad.sh -t install -l GOAD -p azure\n```\n\nor from the interactive console :\n\n```bash\nGOAD/azure/remote/192.168.56.X > install\n```\n\n## start/stop/status\n\n- You can see the status of the lab with the command `status`\n- You can also start and stop the lab with the command `start` and `stop`\n\n!!! info\n    The command `stop` use deallocate, it take a long time to run but it is not only stopping the vms, it will deallocate them. By doing that, you will stop paying from them (but you still paying storage) and can save some money.\n\n## VMs sku\n\n- The vm used for goad are defined in the lab terraform file : `ad/<lab>/providers/azure/windows.tf`\n- This file is containing information about each vm in use\n\n```\n\"dc01\" = {\n  name               = \"dc01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"17763.4377.230505\"\n  private_ip_address = \"{{ip_range}}.10\"\n  password           = \"8dCT-DJjgScp\"\n  size               = \"Standard_B2s\"\n}\n```\n\n## How it works ?\n\n- On the installation goad script will create a folder into `goad/workspaces/<instance_folder>`\n- This folder will contain the terraform scripts and some of the ansible inventories\n- Goad will create the cloud infrastructure with terraform.\n- The lab is created (not provisioned yet) and a \"jumpbox\" vm is also created\n- Next the needed sources will be pushed to the jumpbox using `ssh` and `rsync`\n- The jumpbox ssh_key is stored on `goad/workspaces/<instance_folder>/ssh_keys`\n- The jumpbox is prepared to run ansible\n- The provisioning is launch with ssh remotely on the jumpbox\n\n## Install step by step\n\n```bash\nGOAD/azure/remote/192.168.56.X > create_empty # create empty instance\nGOAD/azure/remote/192.168.56.X > load <instance_id>\nGOAD/azure/remote/192.168.56.X (<instance_id>) > provide # play terraform\nGOAD/azure/remote/192.168.56.X (<instance_id>) > sync_source_jumpbox # sync jumpbox source\nGOAD/azure/remote/192.168.56.X (<instance_id>) > prepare_jumpbox # install dependencies on jumpbox\nGOAD/azure/remote/192.168.56.X (<instance_id>) > provision_lab # run ansible\n```\n\n## Tips\n\n- To connect to the jumpbox VM you can use `ssh_jumpbox` in the goad interactive console\n- To setup a socks proxy you can use `ssh_jumpbox_proxy <proxy_port>` in the goad interactive console\n\n- If the command `destroy` or `delete` fails, you can delete the resource group using the CLI\n```bash\naz group delete --name GOAD\n```"
  },
  {
    "path": "docs/mkdocs/docs/providers/index.md",
    "content": "# 🏗 Providers\n\n- Providers are used to create and deploy the lab virtual machine.\n\n- Goad actually support the following providers:\n    - On your own computer :\n        - :simple-virtualbox: [Virtualbox](virtualbox.md)\n        - :simple-vmware: [VmWare](vmware.md)\n\n    - Cloud :\n        - :material-microsoft-azure: [Azure](azure.md)\n        - :simple-amazon: [Aws](aws.md)\n\n    - Hypervisor :\n        - :simple-proxmox: [Proxmox](proxmox.md)\n        - 🏟️ [Ludus](ludus.md)\n\n> The architecture is slightly different depending on the provider. Please consult the provider you use to understand the behavior."
  },
  {
    "path": "docs/mkdocs/docs/providers/ludus.md",
    "content": "# 🏟️ Ludus\n\n!!! success \"Thanks!\"\n    Huge shootout to @badsectorlabs for Ludus and Erik for his support and tests during the ludus provider creation\n\n<div align=\"center\">\n  <img alt=\"ludus\" width=\"200\" height=\"150\" src=\"./../img/icon_ludus.png\">\n  <img alt=\"icon_ansible\" width=\"145\"  height=\"150\" src=\"./../img/icon_ansible.png\">\n</div>\n\n!!! warning \"Install on ludus server only\"\n    To add GOAD on Ludus please use goad directly on the server.\n    By now goad can work only directly on the server and not from a workstation client.\n\n!!! info \"V2\"\n    for ludus v2 create an environment variable : `export LUDUS_VERSION=2`\n\n- Install Ludus : [https://docs.ludus.cloud/docs/quick-start/install-ludus/](https://docs.ludus.cloud/docs/quick-start/install-ludus/)\n\n- Be sure to create an **admin** user and keep his api key\n- Once your installation is complete on ludus server (debian 12) and your user is created do :\n\n```bash\ngit clone https://github.com/Orange-Cyberdefense/GOAD.git\ncd GOAD\nsudo apt install python3.11-venv        # because by default ludus use debian 12 with python3.11\nexport LUDUS_API_KEY='myapikey'         # put your api key here\n./goad.sh -p ludus\nGOAD/ludus/local > check\nGOAD/ludus/local > set_lab XXX # GOAD/GOAD-Light/NHA/SCCM\nGOAD/ludus/local > install\n```\n\nAnd goad launch the installation ;)\n\n## Goad configuration\n\n- If you don't want to do the export LUDUS_API_KEY before using goad you can also add the api_key in the goad.ini configuration file\n- The goad configuration file as some options for ludus:\n\n```\n# ~/.goad/goad.ini\n...\n[ludus]\nludus_api_key = changeme\nuse_impersonation = yes\n```\n\n- change the api_key with the one of your admin user\n\n## Install\n\n```bash\n./goad.sh -p ludus\nGOAD/ludus/local > set_lab XXX # GOAD/GOAD-Light/NHA/SCCM\nGOAD/ludus/local > install\n```\n\n- The installation will create a new simple_user to generate the pool we will call him \"lab_user\" the id of this user will be `lab_name<6alphanumeric_digit>`\n- Next this \"lab_user\" will be impersonate to launch all the ludus deployment command\n- At the end the \"lab_user\" will share access to our user\n- This way we can manage multiple lab instance with goad on the same ludus server.\n\n!!! info\n    On ludus the config ip_range is not used and is ignored. The ips will be setup automatically during the lab installation"
  },
  {
    "path": "docs/mkdocs/docs/providers/proxmox.md",
    "content": "# :simple-proxmox: Proxmox\n\n<div align=\"center\">\n  <img alt=\"terraform\" width=\"166\" height=\"150\" src=\"./../img/icon_terraform.png\">\n  <img alt=\"terraform\" width=\"205\" height=\"150\" src=\"./../img/icon_proxmox.png\">\n  <img alt=\"icon_ansible\" width=\"150\"  height=\"150\" src=\"./../img/icon_ansible.png\">\n</div>\n\n- A complete guide to proxmox installation is available here : [https://mayfly277.github.io/categories/proxmox/](https://mayfly277.github.io/categories/proxmox/)\n\n## Prerequisites\n\n- [Packer](https://developer.hashicorp.com/packer/downloads?product_intent=packer)\n- [Terraform](https://www.terraform.io/downloads.html)\n\n## Installation\n\n- Once you have prepared your provisioning vm (you can use the scripts/setup_proxmox.sh for prerequistes installation)\n- And once your prerequisites are ready see [https://mayfly277.github.io/posts/GOAD-on-proxmox-part2-packer/](https://mayfly277.github.io/posts/GOAD-on-proxmox-part2-packer/) to prepare the template for proxmox\n\n\n- You can run the automatic installation\n\n```bash\n# check prerequisites\n./goad.sh -t check -l GOAD -p proxmox\n# Install\n./goad.sh -t install -l GOAD -p proxmox\n```\n"
  },
  {
    "path": "docs/mkdocs/docs/providers/virtualbox.md",
    "content": "# :simple-virtualbox: Virtualbox\n\n<div align=\"center\">\n  <img alt=\"vagrant\" width=\"153\" height=\"150\" src=\"../img/icon_vagrant.png\">\n  <img alt=\"icon_virtualbox\" width=\"150\"  height=\"150\" src=\"../img/icon_virtualbox.png\">\n  <img alt=\"icon_ansible\" width=\"150\"  height=\"150\" src=\"../img/icon_ansible.png\">\n</div>\n\n## Prerequisites\n\n- Providing\n    - [Virtualbox](https://www.virtualbox.org/)\n    - [Vagrant](https://developer.hashicorp.com/vagrant/docs)\n    - Vagrant plugins:\n        - vagrant-reload\n        - vagrant-vbguest \n        - winrm\n        - winrm-fs\n        - winrm-elevated\n\n- Provisioning\n    - Python3 >=3.8\n    - goad requirements\n    - ansible-galaxy goad requirements\n\n\n## Check dependencies\n\n```bash\n./goad.sh -p virtualbox\nGOAD/virtualbox/local/192.168.56.X > check\n```\n\n![vbox_check_example.png](./../img/vbox_check_example.png)\n\n!!! info\n    If there is some missing dependencies goes to the [installation](../installation/index.md) chapter and follow the guide according to your os.\n\n!!! note\n    check give mandatory dependencies in red and non mandatory in yellow (but you should be compliant with them too depending one your operating system)\n\n## Install\n\n- To install run the goad script and launch install or use the goad script arguments\n\n```bash\n./goad.sh -p virtualbox\nGOAD/virtualbox/local/192.168.56.X > set_lab <lab>  # here choose the lab you want (GOAD/GOAD-Light/NHA/SCCM)\nGOAD/virtualbox/local/192.168.56.X > set_ip_range <ip_range>  # here choose the  ip range you want to use ex: 192.168.56\nGOAD/virtualbox/local/192.168.56.X > install\n```\n\n![vbox_install](./../img/vbox_install.png)\n\n- or all in command line with arguments\n\n```bash\n./goad.sh -t install -p virtualbox -l <lab> -ip <ip_range_to_use>\n```"
  },
  {
    "path": "docs/mkdocs/docs/providers/vmware.md",
    "content": "# :simple-vmware: Vmware\n\n!!! quote\n    \"Virtualbox c'est no way\" @mpgn\n\n<div align=\"center\">\n  <img alt=\"vagrant\" width=\"153\" height=\"150\" src=\"../img/icon_vagrant.png\">\n  <img alt=\"icon_vwmare\" width=\"176\"  height=\"150\" src=\"../img/icon_vwmare.png\">\n  <img alt=\"icon_ansible\" width=\"150\"  height=\"150\" src=\"../img/icon_ansible.png\">\n</div>\n\n## Prerequisites\n\n- Providing \n    - [Vmware workstation](https://support.broadcom.com/group/ecx/productdownloads?subfamily=VMware+Workstation+Pro)\n    - [Vagrant](https://developer.hashicorp.com/vagrant/docs)\n    - [Vmware utility driver](https://developer.hashicorp.com/vagrant/install/vmware)\n    - Vagrant plugins:\n        - vagrant-reload\n        - vagrant-vmware-desktop\n        - winrm\n        - winrm-fs\n        - winrm-elevated\n\n- Provisioning\n    - Python3 >=3.8\n    - goad requirements\n    - ansible-galaxy goad requirements\n\n\n## check dependencies\n\n```bash\n./goad.sh -p vmware\nGOAD/vmware/local/192.168.56.X > check\n```\n\n![vmware_check.png](./../img/vmware_check.png)\n\n!!! info\n    If there is some missing dependencies goes to the [installation](../installation/index.md) chapter and follow the guide according to your os.\n\n!!! note\n    check give mandatory dependencies in red and non mandatory in yellow (but you should be compliant with them too depending one your operating system)\n\n## Install\n\n- To install run the goad script and launch install or use the goad script arguments\n\n```bash\n./goad.sh -p vmware\nGOAD/vmware/local/192.168.56.X > set_lab <lab>  # here choose the lab you want (GOAD/GOAD-Light/NHA/SCCM)\nGOAD/vmware/local/192.168.56.X > set_ip_range <ip_range>  # here choose the  ip range you want to use ex: 192.168.56 (only the first three digits)\nGOAD/vmware/local/192.168.56.X > install\n```\n\n![vmware_install](./../img/vmware_install.png)\n\n- or all in command line with arguments\n\n```bash\n./goad.sh -t install -p vmware -l <lab> -ip <ip_range_to_use>\n```\n"
  },
  {
    "path": "docs/mkdocs/docs/providers/vmware_esxi.md",
    "content": "# :simple-vmware: Vmware ESXi\n\n!!! success \"Thanks!\"\n    Thanks to [fsacer](https://github.com/fsacer) and  [viris](https://github.com/viris) for the pr [330](https://github.com/Orange-Cyberdefense/GOAD/pull/330) for vmware esxi provider support\n\n<div align=\"center\">\n  <img alt=\"vagrant\" width=\"153\" height=\"150\" src=\"../img/icon_vagrant.png\">\n  <img alt=\"icon_vmmare_esxi\" width=\"176\"  height=\"150\" src=\"../img/icon_vmware_esxi.png\">\n  <img alt=\"icon_ansible\" width=\"150\"  height=\"150\" src=\"../img/icon_ansible.png\">\n</div>\n\n## Prerequisites\n\n- Providing\n  - [VMWare ESXi](https://www.vmware.com/products/esxi-and-esx.html) - [no longer free](https://kb.vmware.com/s/article/2107518)\n  - [Vagrant](https://developer.hashicorp.com/vagrant/docs)\n  - Vagrant plugins:\n    - vagrant-reload\n    - vagrant-vmware-esxi\n    - vagrant-env\n    - on some distribution also the vagrant plugins :\n      - winrm\n      - winrm-fs\n      - winrm-elevated\n  - ovftool (https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest)\n\n- Provisioning with python\n  - Python3 (>=3.8)\n  - [ansible-core==2.12.6](https://docs.ansible.com/ansible/latest/index.html)\n  - pywinrm\n\n- Or provisioning With Docker\n  - [Docker](https://www.docker.com/)\n\n## check dependencies\n\n```bash\n./goad.sh -p vmware_esxi\nGOAD/vmware_esxi/local/192.168.56.X > check\n```\n\n![esxi_check.png](./../img/esxi_check.png)\n\n!!! info\n    If there is some missing dependencies goes to the [installation](../installation/index.md) chapter and follow the guide according to your os.\n\n!!! note\n    check give mandatory dependencies in red and non mandatory in yellow (but you should be compliant with them too depending one your operating system)\n\n## Install\n\n- To install run the goad script and launch install or use the goad script arguments\n\n```bash\n./goad.sh -p vmware_esxi\nGOAD/vmware_esxi/local/192.168.56.X > set_lab <lab>  # here choose the lab you want (GOAD/GOAD-Light/NHA/SCCM)\nGOAD/vmware_esxi/local/192.168.56.X > set_ip_range <ip_range>  # here choose the  ip range you want to use ex: 192.168.56 (only the first three digits)\nGOAD/vmware_esxi/local/192.168.56.X > install\n```\n\n![esxi_install](./../img/esxi_install.png)\n\n- or all in command line with arguments\n\n```bash\n./goad.sh -t install -p vmware_esxi -l <lab> -ip <ip_range_to_use>\n```"
  },
  {
    "path": "docs/mkdocs/docs/provisioning.md",
    "content": "# :material-ansible: provisioning\n\nThis page describe how the provisioning is done with goad.\nThe provisioning of the LABS is done with Ansible for all providers.\n\n- First the GOAD install script create an instance folder in the workspace folder.\n\n## Lab data\n\nThe data of each lab are stored in the json file : `ad/<lab>/data/config.json`, this file is loaded by each playbook to get all the lab variables (this is done by the data.yml playbook call by all the over playbooks)\n\n## Extension data\n\nIf an extension need data it will be stored in `extensions/<extension>/data/config.json` but the loading must be done by extension install.yml playbook.\n\n- Example with the exchange install.yml file :\n\n```\n# read local configuration file\n- name: \"Read local config file\"\n  hosts: domain:extensions\n  connection: local\n  vars_files:\n    - \"../data/config.json\"\n  tasks:\n    - name: merge lab variable with local config\n      set_fact:\n        lab: \"{{ lab|combine(lab_extension, recursive=True) }}\"\n```\n\n## Inventories\n\nAnsible work with inventories. Inventories files contains all the hosts declaration and some variables.\n\n- The lab inventory file (`ad/<lab>/data/inventory`) is not modified/moved and contain all the main variables and hosts association, this file stay as this and is not modified. It contains the lab building logic.\n\n- The provider inventory file (`ad/<lab>/provider/<provider>/inventory`) is modified with the settings and copied into the workspace folder (`workspace/<instance_id>/inventory`) , this file contains variable specific to the provider and the host ip declaration\n\n- The extension(s) inventory file(s) (`extensions/<extension>/inventory`) is modified with the settings and copied into the workspace folder (`workspace/<instance_id>/inventory_<extension>`) , this file contains variable specific to the extension and the extension host ip declaration\n\n- The global inventory file `globalsettings.ini`contains some global variable with some user settings.\n\n\nThe inventory files are given to ansible in this order :\n- lab inventory file\n- workspace provider inventory file\n- workspace extension(s) inventory file(s)\n- globalsettings.ini file\n\nThe order is important as it determine the override order. hosts declarations are merged between all inventory and variables with the same name are override if the same variable is declared. \n\n- Example : if i setup dns_server_forwarder=8.8.8.8 in the lab inventory file and dns_server_forwarder=1.1.1.1 in the globalsettings.ini file, the final value for ansible wll be dns_server_forwarder=1.1.1.1\n\n## playbooks\n\n- Labs playbook are stored on the ansible/ folder\n- Extension playbook is stored in `extension/<extension>/ansible/install.yml`\n- The extension folder can call the main goad roles by using a special ansible.cfg file.\n\n- Example of the exchange ansible.cfg file\n```\n[defaults]\n...\n; add default roles folder into roles_path\nroles_path = ./roles:../../../ansible/roles\n```\n\n## labs build\n\n- Instead of call a global main.yml playbook with all the different tasks to do the goad script call each playbook one by one.\n- In this way, there is a fallback mecanism to retry each playbook 3 times before consider it as failed.\n- The list and order of the playbooks played are stored in the playbooks.yml file at the start of the project."
  },
  {
    "path": "docs/mkdocs/docs/questions.md",
    "content": "# Frequent asked questions\n\n\n!!! question \"How can i change the default keyboard layout ?\"\n    edit globalsettings.ini files and change the variable `keyboard_layouts`\n\n!!! question \"How can i change the folder where vagrant download the boxes ?\"\n    vagrant download the boxes by default on ~/.vagrant.d/ folder. Set up the VAGRANT_HOME environment variable to change this location.\n\n!!! question \"How can i change the folder where virtualbox create the box ?\"\n    Go to virtualbox preferences and change the virtualbox vm location folder.\n\n!!! question \"I already got a lab installed with v2, is v3 will use it ?\"\n    Sorry no, the v3 of GOAD doesn't look for already installed lab. Best way to migrate is trash your old lab and build a new one.\n\n!!! question \"Can i use goad to create a course for my student ?\"\n    Sure GOAD is a GPL project. Feel free to reuse it to give course. Just don't forget to give credits to the project ;)"
  },
  {
    "path": "docs/mkdocs/docs/references.md",
    "content": "# References\n\n🚧 TODO TO BE COMPLETED\n\n- Mayfly's blog : \n    - [GOAD writeups](https://mayfly277.github.io/categories/goad/)\n    - [SCCM writeups](https://mayfly277.github.io/categories/sccm/)\n    - [Proxmox Install](https://mayfly277.github.io/categories/proxmox/)\n\n- NHA WriteUp :\n    - [crypt0ace's blog NHA writeup](https://crypt0ace.github.io/posts/NHA-Part-1/)\n    - [mr-stark's blog NHA writeup](https://www.notion.so/mr-stark/NINJA-HACKER-ACADEMY-30c79e9ad7c98066a0f9f8c4c0892be5)\n\n- Podcast\n    - [Hackn'speak episode 0x1B (FR)](https://podcasts-francais.fr/podcast/hack-n-speak)\n\n- YouTube\n    - [Game Of Active Directory With Elastic by I.T security labs](https://www.youtube.com/playlist?list=PLyJqGMYm0vnNcwX1_jT_c6R7EaA0EqJHO)\n    - [HackTheClown Playlist on GOAD-Light](https://www.youtube.com/playlist?list=PL08nYpWQJ_zM4JxekcckBVjglpVWgg2u0)\n    - [Game of Active Directory enumeration by qdada](https://www.youtube.com/playlist?list=PLMl69W33-fZUuOSmoPF1gAW3Wku84xspT)"
  },
  {
    "path": "docs/mkdocs/docs/stylesheets/extra.css",
    "content": "/*@media only screen and (min-width: 76.25em) {\n    .md-main__inner {\n      max-width: none;\n    }\n    .md-sidebar--primary {\n      left: 0;\n    }\n    .md-sidebar--secondary {\n      right: 0;\n      margin-left: 0;\n      -webkit-transform: none;\n      transform: none;   \n    }\n  }\n*/\n.md-header__button.md-logo img, .md-header__button.md-logo svg {\nfill: currentcolor;\ndisplay: block;\nheight: 3.0rem;\nwidth: auto;\n}\n\nh1 {\n  font-weight: bold;\n}\n\nh1, h2 {\n  border-bottom: 1px solid #2f3032; /* Adjust thickness and color */\n  padding-bottom: 10px; /* Adds spacing between text and the border */\n}\n\nnav .md-nav--primary {\n  border-right: 1px solid #2f3032;\n}\n\nnav.md-nav--secondary{\n  border-left: 1px solid #2f3032;\n}\n"
  },
  {
    "path": "docs/mkdocs/docs/thx.md",
    "content": "# Special Thanks to\n\n- [@KenjiEndo15](https://x.com/KenjiEndo15) for all his work on the SCCM ansible roles and his contribution to the SCCM Lab\n- [aleemladha](https://github.com/aleemladha) for exchange and ludus ansible roles\n- [Erik @badsectorlabs](https://x.com/badsectorlabs) for his advises and tests during the [Ludus](https://docs.ludus.cloud/) provider creation\n- [@ArnC_CarN](https://github.com/ArnCo) for his PR on the aws provider\n- [@Sant0rryu](https://x.com/Sant0rryu) for his help during ADCS vulnerabilities creation\n- All the Orange Cyberdefense Toulouse team for the beta tests on the NHA lab ;)\n- Julien Arrault (For the Azure recipes creation)\n- Thomas Rollain (For his tests & some vulns writing during v1 creation)\n- Quentin Galliou (For his tests during v1 creation)\n\nAnd of course to all the [project contributors](https://github.com/Orange-Cyberdefense/GOAD/graphs/contributors) !\n\n## Enterprise\n\n- [Orange Cyberdefense](https://www.orangecyberdefense.com/fr/) to give me time to work on the project, and let me put the project in GPL on the Orange Cyberdefense's GitHub repository."
  },
  {
    "path": "docs/mkdocs/docs/troobleshoot.md",
    "content": "# troubleshoot\n\n!!! tip\n    In most case if you get errors during install, don't think. \n    Select the failed instance ̀`load <instance_id>` and just replay the install with `provision_lab` to relaunch all or `provision_lab_from <playbook>` if you know the last failed playbook \n    (most of the errors which could came up are due to windows latency during installation, wait few minutes and replay the install)\n\n🚧 TODO refresh me with new goad version :)\n\n\n## vagrant up - WinRM - digest initialization failed : Initialization Error\n\n```\nDC01: WinRM username: vagrant\nDC01: WinRM execution_time_limit: PT2H\nDC01: WinRM transport: negotiate\nAn error occurred executing a remote WinRM command.\n\nShell: Cmd\nCommand: hostname\nMessage: Digest initialization failed: initialization error\n```\n\n- solution 1: change vagrantfile to not use ssl (https://github.com/Orange-Cyberdefense/GOAD/issues/68)\n    - add this lines in vagrantfile to not use ssl :\n        ```\n        config.winrm.transport = \"plaintext\"\n        config.winrm.basic_auth_only = true\n        ```\n- solution 2: allow legacy algorithm (https://github.com/Orange-Cyberdefense/GOAD/issues/11)\n    - add to /etc/ssl/openssl.conf :\n    ```\n    [provider_sect]\n    default = default_sect\n    legacy = legacy_sect\n\n    [default_sect]\n    activate = 1\n\n    [legacy_sect]\n    activate = 1\n    ```\n\n- solution 3: downgrade the vagrant version (`sudo apt install vagrant=2.2.19`)\n\n## vagrant up - cannot load \n\n```\n<internal:/usr/lib/ruby/vendor_ruby/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- winrm (LoadError)\n\tfrom <internal:/usr/lib/ruby/vendor_ruby/rubygems/core_ext/kernel_require.rb>:85:in `require'\n\tfrom /usr/share/rubygems-integration/all/gems/vagrant-2.3.4/plugins/communicators/winrm/shell.rb:9:in `block in <top (required)>'\n\tfrom /usr/share/rubygems-integration/all/gems/vagrant-2.3.4/lib/vagrant/util/silence_warnings.rb:8:in `silence!'\n```\n\n- solution : \n  - `gem install winrm`\n  - `gem install winrm-fs`\n\n\n## vagrant up - cannot load such file -- winrm-elevated (LoadError)\n\n```\n<internal:/usr/lib/ruby/vendor_ruby/rubygems/core_ext/kernel_require.rb>:85:in `require': cannot load such file -- winrm-elevated (LoadError)\n        from <internal:/usr/lib/ruby/vendor_ruby/rubygems/core_ext/kernel_require.rb>:85:in `require'\n        from /usr/share/rubygems-integration/all/gems/vagrant-2.3.4/plugins/communicators/winrm/shell.rb:12:in `<top (required)>'\n        ...\n```\n\n- solution : `gem install winrm-elevated`\n\n\n## ansible persistent \"unreachable error\"\n\n- Unreachable means ansible can't contact the vms. \n- Maybe the vms didn't got the right ip? (try to connect with vagrant/vagrant on vm and look the ip)\n- Or you got a firewall on the vm which do provisioning which block winrm connection ?\n- or maybe it is a vagrant issue : https://github.com/Orange-Cyberdefense/GOAD/issues/12\n- You could try to switch on port 5985 to connect without ssl as suggest here : https://github.com/Orange-Cyberdefense/GOAD/issues/98 by uncomment the lines in the inventory file you use\n```\n# ansible_winrm_transport=basic\n# ansible_port=5985\n```\n\n## The naming context specified for this replication operation is invalid\n\n```\nTASK [groups_domains : synchronizes all domains] *******************************************************************************************************************************************************************************************************************************\nchanged: [dc03]\nchanged: [dc01]\nfatal: [dc02]: FAILED! => {\"changed\": true, \"cmd\": \"repadmin /syncall /Ade\", \"delta\": \"0:00:01.090773\", \"end\": \"2023-10-18 09:30:26.016579\", \"msg\": \"non-zero return code\", \"rc\": 1, \"start\": \"2023-10-18 09:30:24.925805\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"Syncing all NC's held on winterfell.\\r\\r\\nSyncing partition: DC=north,DC=sevenkingdoms,DC=local\\r\\r\\nCALLBACK MESSAGE: Error contacting server CN=NTDS Settings,CN=WINTERFELL,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=sevenkingdoms,DC=local (network error): 1722 (0x6ba):\\r\\r\\n    The RPC server is unavailable.\\r\\r\\n\\r\\r\\nSyncAll exited with fatal Win32 error: 8440 (0x20f8):\\r\\r\\n    The naming context specified for this replication operation is invalid.\\r\\r\\n\", \"stdout_lines\": [\"Syncing all NC's held on winterfell.\", \"\", \"Syncing partition: DC=north,DC=sevenkingdoms,DC=local\", \"\", \"CALLBACK MESSAGE: Error contacting server CN=NTDS Settings,CN=WINTERFELL,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=sevenkingdoms,DC=local (network error): 1722 (0x6ba):\", \"\", \"    The RPC server is unavailable.\", \"\", \"\", \"\", \"SyncAll exited with fatal Win32 error: 8440 (0x20f8):\", \"\", \"    The naming context specified for this replication operation is invalid.\", \"\"]}\n```\n\n- relaunch install\n\n## vagrant up - Vagrant can't use the requested machine because it is locked \n\n```\n==> GOAD-SRV03: Configuring and enabling network interfaces...\nVagrant can't use the requested machine because it is locked! This\nmeans that another Vagrant process is currently reading or modifying\nthe machine. Please wait for that Vagrant process to end and try\nagain. Details about the machine are shown below:\n```\n\n- solution : relaunch the provisioning on the broken computer : \n- exemple :\n```\ncd ~/GOAD/ad/GOAD/providers/virtualbox\nvagrant reload GOAD-SRV03 --provisioning\n```\n- and than relaunch the install script\n\n## The server has rejected the client credentials\n\n```\nAn exception occurred during task execution. To see the full traceback, use -vvv. The error was:    at Microsoft.ActiveDirectory.Management.Commands.ADCmdletBase`1.BeginProcessing()\nfailed: [dc02] (item={'key': 'AcrossTheSea', 'value': ['essos.local\\\\daenerys.targaryen']}) => {\"ansible_loop_var\": \"item\", \"attempts\": 3, \"changed\": false, \"item\": {\"key\": \"AcrossTheSea\", \"value\": [\"essos.local\\\\daenerys.targaryen\"]}, \"msg\": \"Unhandled exception while executing module: The server has rejected the client credentials.\"}\n```\n\n- something go wrong with the trust, all the links are not fully establish\n- wait several minutes and relaunch the install\n\n## Groups domain error\n\n- something go wrong with the trust, all the links are not fully establish\n- wait several minutes and relaunch the playbook\n- i really don't know why this append time to time on installation, if you want to investigate and resolve the issue please tell me how.\n\n```bash\nAn exception occurred during task execution. To see the full traceback, use -vvv. The error was:    at Microsoft.ActiveDirectory.Management.Commands.ADCmdletBase`1.BeginProcessing()\nfailed: [192.168.56.xx] (item={'key': 'DragonsFriends', 'value': ['sevenkingdoms.local\\\\tyron.lannister', 'essos.local\\\\daenerys.targaryen']}) => {\"ansible_loop_var\": \"item\", \"attempts\": 3, \"changed\": false, \"item\": {\"key\": \"DragonsFriends\", \"value\": [\"north.sevenkingdoms.local\\\\jon.snow\", \"sevenkingdoms.local\\\\tyron.lannister\", \"essos.local\\\\daenerys.targaryen\"]}, \"msg\": \"Unhandled exception while executing module: Either the target name is incorrect or the server has rejected the client credentials.\"}\n```\n\n## Error Add-Warning\n\n- You got an \"Add-Warning\" error during the user installation.\n- Upgrade to community.windows galaxy >= 1.11.0\n- relaunch the ansible playbooks.\n\n```bash\nAn exception occurred during task execution. To see the full traceback, use -vvv. The error was: at , : line 475\nfailed: [192.168.56.11] (item={'key': 'arya.stark', 'value': {'firstname': 'Arya', 'surname': 'Stark',\n...\n\"msg\": \"Unhandled exception while executing module: The term 'Add-Warning' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.\"}+\n```\n\n## A parameter cannot be found that matches parameter name 'AcceptLicense'\n\n- If you got this kind of error you got an ansible.windows version >=  1.11.0\n- This version add the parameter AcceptLicense but it is accepted only for PowerShellGet module >= 1.6.0 and this one is not embedded in the vms.\n- Please keep version 1.11.0 and update the lab to get the fix for the PowerShellGet Module version.\n\n```bash\nfatal: [xxx]: FAILED! => {\n    \"changed\": false,\n    \"msg\": \"Problems installing XXXX module: A parameter cannot be found that matches parameter name 'AcceptLicense'.\",\n    \"nuget_changed\": false,\n    \"output\": \"\",\n    \"repository_changed\": false\n}\n```\n\n## old Ansible version\n\n```bash\nERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.\n \nThe error appears to have been in '/home/hrrb0032/Documents/mission/GOAD/roles/domain_controller/tasks/main.yml': line 8, column 3, but maybe elsewhere in the file depending on the exact syntax problem.\n \nThe offending line appears to be:\n \n- name: disable enhanced exit codes\n^ here\n```\n\nsolution : upgrade Ansible\n\n### old ansible.windows version\n```bash\nERROR! couldn't resolve module/action 'win_powershell'. This often indicates a misspelling, missing collection, or incorrect module path.\n```\n\n- solution: reinstall ansible.windows module :\n```bash\nansible-galaxy collection install ansible.windows --force\n```\n\n## winrm\n\n```bash\nPLAY [DC01 - kingslanding] *******************************************************\n\n \n\nTASK [Gathering Facts] ***********************************************************\nfatal: [192.168.56.10]: FAILED! => {\"msg\": \"winrm or requests is not installed: No module named winrm\"}\n\n \n\nPLAY RECAP ***********************************************************************\n192.168.56.10              : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   \n```\n\nsolution : pip install pywinrm\n\n\n\n## winrm send input timeout\n\n```bash\nTASK [Gathering Facts] ****************************************************************************************************************************************************\n[WARNING]: ERROR DURING WINRM SEND INPUT - attempting to recover: WinRMOperationTimeoutError\nok: [192.168.56.11]\n```\n\nsolution : wait or if crashed then re-run install\n\n\n\n## Domain controller : ensure Users are present \n\n```bash\nTASK [domain_controller : Ensure that Users presents in ou=<kingdom>,dc=SEVENKINGDOMS,dc=local] ***************************************************************************\nAn exception occurred during task execution. To see the full traceback, use -vvv. The error was:    at Microsoft.ActiveDirectory.Management.Commands.ADCmdletBase`1.ProcessRecord()\nfailed: [192.168.56.10] (item={u'key': u'lord.varys', u'value': {u'city': u\"King's Landing\", u'password': u'_W1sper_$', u'name': u'Lord Varys', u'groups': u'Small Council', u'path': u'OU=Users,OU=Crownlands,OU=kingdoms,DC=SEVENKINGDOMS,DC=local'}}) => {\"ansible_loop_var\": \"item\", \"changed\": false, \"item\": {\"key\": \"lord.varys\", \"value\": {\"city\": \"King's Landing\", \"groups\": \"Small Council\", \"name\": \"Lord Varys\", \"password\": \"_W1sper_$\", \"path\": \"OU=Users,OU=Crownlands,OU=kingdoms,DC=SEVENKINGDOMS,DC=local\"}}, \"msg\": \"Unhandled exception while executing module: An unspecified error has occurred\"}\n\n```\n solution : re-run install\n\n## mssql : Unable to install SQL Server\n```\nTASK [mssql : Install the database]\nfatal: [192.168.56.22]: FAILED! => {\"attempts\": 3, \"changed\": true, \"cmd\": \"c:\\\\setup\\\\mssql\\\\sql_installer.exe /configurationfile=c:\\\\setup\\\\mssql\\\\sql_conf.ini /IACCEPTSQLSERVERLICENSETERMS /MEDIAPATH=c:\\\\setup\\\\mssql\\\\media /QUIET /HIDEPROGRESSBAR\", \"delta\": \"0:00:34.891185\", \"end\": \"2022-08-17 21:26:53.976793\", \"msg\": \"non-zero return code\", \"rc\": 2226323458, \"start\": \"2022-08-17 21:26:19.085608\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"Microsoft (R) SQL Server Installer\\r\\nCopyright (c) 2019 Microsoft.  All rights reserved.\\r\\n\\r\\nDownloading install package...\\r\\n\\r\\n\\r\\nOperation finished with result: Failure\\r\\n\\r\\nOops...\\r\\n\\r\\nUnable to install SQL Server (setup.exe).\\r\\n\\r\\n      Exit code (Decimal): -2068643838\\r\\n      Exit message: No features were installed during the setup execution. The requested features may already be installed. Please review the summary.txt log for further details.\\r\\n\\r\\n  SQL SERVER INSTALL LOG FOLDER\\r\\n      c:\\\\Program Files\\\\Microsoft SQL Server\\\\150\\\\Setup Bootstrap\\\\Log\\\\20220817_142624\\r\\n\\r\\n\", \"stdout_lines\": [\"Microsoft (R) SQL Server Installer\", \"Copyright (c) 2019 Microsoft.  All rights reserved.\", \"\", \"Downloading install package...\", \"\", \"\", \"Operation finished with result: Failure\", \"\", \"Oops...\", \"\", \"Unable to install SQL Server (setup.exe).\", \"\", \"      Exit code (Decimal): -2068643838\", \"      Exit message: No features were installed during the setup execution. The requested features may already be installed. Please review the summary.txt log for further details.\", \"\", \"  SQL SERVER INSTALL LOG FOLDER\", \"      c:\\\\Program Files\\\\Microsoft SQL Server\\\\150\\\\Setup Bootstrap\\\\Log\\\\20220817_142624\", \"\"]}\n```\n\nsolution : re-run installer\n\n\n## vagrant: Not working on Ubuntu 22.04\n\nI was using the version of Vagrant in the Ubuntu repo, and then tried to use the version 2.4.0 and 2.3.4 binaries from hashicorp, but kept on running into this error:\n\n```\nThe guest machine entered an invalid state while waiting for it\nto boot. Valid states are 'starting, running'. The machine is in the\n'poweroff' state. Please verify everything is configured\nproperly and try again.\n\nIf the provider you're using has a GUI that comes with it,\nit is often helpful to open that and watch the machine, since the\nGUI often has more helpful error messages than Vagrant can retrieve.\nFor example, if you're using VirtualBox, run `vagrant up` while the\nVirtualBox GUI is open.\n\nThe primary issue for this error is that the provider you're using\nis not properly configured. This is very rarely a Vagrant issue.\n```\nSolution : install vagrant from the hashicorp repo\n\n## proxmox: error creating VM: 403 Permission check failed (/sdn/zones/localnetwork/vmbr3/10, SDN.Use)\n\nThe error may look similar to below:\n```\n==> proxmox-iso.windows: Error creating VM: error creating VM: 403 Permission check failed (/sdn/zones/localnetwork/vmbr3/10, SDN.Use), \nerror status: {\"data\":null} (params: ......\n```\n\nIt may be fixed by delegating the SDN.Use privilege to the packer user\n```\npveum role modify Packer -privs \"VM.Config.Disk VM.Config.CPU VM.Config.Memory Datastore.AllocateTemplate Datastore.Audit Datastore.AllocateSpace Sys.Modify VM.Config.Options VM.Allocate VM.Audit VM.Console VM.Config.CDROM VM.Config.Cloudinit VM.Config.Network VM.PowerMgmt VM.Config.HWType VM.Monitor SDN.Use\"\n```\n\n## proxmox: ==> proxmox-iso.windows: Error creating VM: error creating VM: unable to create VM 103 - unsupported format 'qcow2' \n\nThe error may look similar to below:\n```\nroot@goadprovisioning:~/GOAD/packer/proxmox# packer build -var-file=windows_server2019_proxmox_cloudinit.pkvars.hcl .\nproxmox-iso.windows: output will be in this color.\n\n==> proxmox-iso.windows: Retrieving additional ISO\n==> proxmox-iso.windows: Trying ./iso/Autounattend_winserver2019_cloudinit.iso\n==> proxmox-iso.windows: Trying ./iso/Autounattend_winserver2019_cloudinit.iso?checksum=sha256%3A43857cb780de3a58696285f644034499d4b29608b3c511feb27e315832b696c4\n==> proxmox-iso.windows: ./iso/Autounattend_winserver2019_cloudinit.iso?checksum=sha256%3A43857cb780de3a58696285f644034499d4b29608b3c511feb27e315832b696c4 => /root/GOAD/packer/proxmox/iso/Autounattend_winserver2019_cloudinit.iso\n    proxmox-iso.windows: Uploaded ISO to local:iso/Autounattend_winserver2019_cloudinit.iso\n==> proxmox-iso.windows: Creating VM\n==> proxmox-iso.windows: No VM ID given, getting next free from Proxmox\n==> proxmox-iso.windows: Error creating VM: error creating VM: unable to create VM 103 - unsupported format 'qcow2' at /usr/share/perl5/PVE/Storage/LvmThinPlugin.pm line 87., error status:  (params: map[agent:1 args: boot: cores:2 cpu:kvm64 description:Packer ephemeral build VM hotplug: ide2:local:iso/windows_server_2019.iso,media=cdrom kvm:true machine: memory:4096 name:WinServer2019x64-cloudinit-qcow2 net0:virtio=5E:5D:24:C4:0F:DA,bridge=vmbr3,tag=10 numa:false onboot:false ostype:win10 pool:GOAD sata0:vms:40,discard=ignore,format=qcow2 scsihw:lsi sockets:1 startup: tags: vmid:103])......\n```\n\nFilesystems such as ZFS (and others) do not support qcow2. From my reading the best approach is to use an ext4 filesystem and modify `config.auto.pkrvars.hcl` with the newly created ext4 volume.\n\n```\nroot@goadprovisioning:~/GOAD/packer/proxmox# vi config.auto.pkrvars.hcl\n...\nproxmox_vm_storage      = \"ext4-qcow2\"\n...\nroot@goadprovisioning:~/GOAD/packer/proxmox# packer build -var-file=windows_server2019_proxmox_cloudinit.pkvars.hcl .\nproxmox-iso.windows: output will be in this color.\n\n==> proxmox-iso.windows: Retrieving additional ISO\n==> proxmox-iso.windows: Trying ./iso/Autounattend_winserver2019_cloudinit.iso\n==> proxmox-iso.windows: Trying ./iso/Autounattend_winserver2019_cloudinit.iso?checksum=sha256%3A43857cb780de3a58696285f644034499d4b29608b3c511feb27e315832b696c4\n==> proxmox-iso.windows: ./iso/Autounattend_winserver2019_cloudinit.iso?checksum=sha256%3A43857cb780de3a58696285f644034499d4b29608b3c511feb27e315832b696c4 => /root/GOAD/packer/proxmox/iso/Autounattend_winserver2019_cloudinit.iso\n    proxmox-iso.windows: Uploaded ISO to local:iso/Autounattend_winserver2019_cloudinit.iso\n==> proxmox-iso.windows: Creating VM\n==> proxmox-iso.windows: No VM ID given, getting next free from Proxmox\n==> proxmox-iso.windows: Starting VM\n```\n\n- another solution is to switch to raw : `proxmox_vm_storage      = \"raw\"`\n\n## proxmox - packer error creating vm :  volume 'local:iso/windows_XXX.iso' does not exist\n\n```\n==> proxmox-iso.windows: Error creating VM: error creating VM: unable to create VM 116 - volume 'local:iso/windows_server2019_XXX_en-us.iso' does not exist, error status:  (params: map[agent:1 args: boot: cores:2 cpu:kvm64 description:Packer ephemeral build VM hotplug\n: ide2:local:iso/windows_server2019_XXX_en-us.iso,media=cdrom kvm:true machine: memory:4096 name:WinServer2019x64-cloudinit-qcow2-uptodate net0:virtio=DA:CB:EB:85:08:0E,bridge=vmbr3,tag=10,firewall=false onboot:false ostype:win10 pool:Templates sata0:local:80,format=q\ncow2 scsihw:lsi sockets:1 startup: tags: vmid:116])   \n```\n\nverify your iso files inside proxmox and be sure the iso you want to use exist in proxmox\n\n## ansible adapter name error \n\n```\nNo MSFT_NetAdapter objects found with property 'Name' equal to 'Ethernet'\n\nor \n\nNo MSFT_NetAdapter objects found with property 'Name' equal to 'Ethernet2 '\n```\n\n- connect to the vm and run ipconfig, verify the adapter name are the same as described in the inventory file.\n- if not change them to match the inventory name in the vm.\n\n## unreachable - proxmox, ansible\n```\nfatal: [dc01]: UNREACHABLE! => {\"changed\": false, \"msg\": \"ssl: HTTPSConnectionPool(host='192.168.10.40', port=5986): Max retries exceeded with url: /wsman\n```\n\n- may be the vm is not well ready after the terraform creation. retry the install.\n- if you still get the error connect to the vm and verify the static ip is corresponding with the one expect.\n\n\n"
  },
  {
    "path": "docs/mkdocs/docs/usage/goad_args.md",
    "content": "# Argument mode\n\n- Launch goad.py script (or goad.sh wrapper) with arguments\n\n```bash\nusage: goad.py [-h] [-t TASK] [-l LAB] [-p PROVIDER] [-ip IP_RANGE] [-m METHOD] [-i INSTANCE] [-e EXTENSIONS] [-a ANSIBLE_ONLY] [-r RUN_PLAYBOOK]\n\nDescription : goad lab management console.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  -t TASK, --task TASK  tasks available : (install/start/stop/restart/destroy/status/show)\n  -l LAB, --lab LAB     lab to use (default: GOAD)\n  -p PROVIDER, --provider PROVIDER\n                        provider to use (default: vmware)\n  -ip IP_RANGE, --ip_range IP_RANGE\n                        ip range to use (default: 192.168.56)\n  -m METHOD, --method METHOD\n                        deploy method to use (default: local)\n  -i INSTANCE, --instance INSTANCE\n                        use a specific instance (use default if not selected)\n  -e EXTENSIONS, --extensions EXTENSIONS\n                        extensions to use\n  -a ANSIBLE_ONLY, --ansible_only ANSIBLE_ONLY\n                        run only provisioning (ansible) on instance (-i) (for task install only)\n  -r RUN_PLAYBOOK, --run_playbook RUN_PLAYBOOK\n                        run only one ansible playbook on instance (-i) (for task install only)\n\nExample :\n - Install GOAD on virtualbox : python3 goad.py -t install -l GOAD -p virtualbox\n - Launch GOAD interactive console : python3 goad.py\n```"
  },
  {
    "path": "docs/mkdocs/docs/usage/goad_console.md",
    "content": "# :material-console-line: GOAD interactive mode\n\nLaunch goad interactive mode\n\n![console](./../img/console.png)\n\n## Enter interactive mode\n\nTo enter interactive mode just launch goad without the `-t` parameter\n\n``` bash\n./goad.sh\n```\n\n## No lab instance selected\n\n```\n*** Lab Instances ***\ncheck ................................... check dependencies before creation\ninstall / create ........................ install the selected lab and create a lab instance\ncreate_empty ............................ prepare a lab instance folder without providing and provisioning\nlist .................................... list lab instances\nload <instance_id> ...................... load a lab instance\n\n*** Configuration ***\nconfig .................................. show current configuration\nlabs .................................... show all labs and available providers\nset_lab <lab> ........................... set the lab to use\nset_provider <provider> ................. set the provider to use\nset_provisioning_method <method> ........ set the provisioning method\nset_ip_range <range> .................... set the 3 first digit of the ip to use (ex: 192.168.56)\n```\n\n### check\n\nWill check the lab dependencies\n\n```\ncheck\n```\n\n![cmd_check](../img/cmd_check.png)\n\n### install\n\nInstall the lab with the current select `config`\n\n```\ninstall\n```\n\n- This will:\n    - create an instance folder into workspaces/\n    - run vagrant/terraform/ludus depending on the provider to create the machines\n    - synchronize source to jumpbox if provider is aws or azure\n    - provision jumpbox if provider is aws or azure\n    - run the ansible provisioning \n\n![cmd_install](../img/cmd_install.png)\n\n### create_empty\n\nCreate an empty instance folder (into the workspaces/ folder)\n\n```\ncreate_empty\n```\n\n![create_empty](../img/cmd_create_empty.png)\n\n### list\n\nList instances\n\n> alias : `ls`\n\n```\nlist\n```\n\n![list](../img/cmd_list.png)\n\n### load\n\nSelect an instance by his name\n\n> alias : `use`, `cd`\n\n```\nload <instance name>\n```\n\n![load](../img/cmd_load.png)\n\n### config\n\nshow current configuration\n\n```\nconfig\n```\n\n![config](../img/cmd_config.png)\n\n### labs\n\nshow available labs\n\n```\nlabs\n```\n\n![cmd_labs.png](../img/cmd_labs.png)\n\n\n### set_lab\n\nChoose the lab to use (GOAD/GOAD-Light/NHA/SCCM/MINILAB)\n\n```\nset_lab <lab_name>\n```\n\n### set_provider\n\nChoose the provider to use (virtualbox/vmware/aws/azure/ludus/proxmox)\n\n```\nset_provider <lab_name>\n```\n\n\n### set_provisioning_method\n\nChoose the provisioning method (local/runner/docker/remote) (most of the time you don't have to change it)\n\n```\nset_provisioning <provisioning_method>\n```\n\n- local : launch ansible with subprocess (default for vbox/vmware/proxmox/ludus)\n- runner : launch ansible with ansible runner\n- remote : launch ansible through ssh using jumpbox (default for azure/aws)\n- docker : user the docker container to launch ansible (docker container must be built first `sudo docker build -t goadansible .`)\n\n### set_ip_range\n\nSet the ip range you want to use (Three first digit, example : 192.168.10)\n\n```\nset_ip_range <ip_range>\n```\n\n\n## Instance selected\n\n![console](../img/console2.png)\n\n```\n*** Manage Lab instance commands ***\nstatus .................................. show current status\nstart ................................... start lab\nstop .................................... stop lab\ndestroy ................................. destroy lab\n\n*** Manage one vm commands ***\nstart_vm <vm_name> ...................... start selected virtual machine\nstop_vm <vm_name> ....................... stop selected virtual machine\nrestart_vm <vm_name> .................... restart selected virtual machine\ndestroy_vm <vm_name> .................... destroy selected virtual machine\n\n*** Extensions ***\nlist_extensions ......................... list extensions\ninstall_extension <extension> ........... install extension (providing + provisioning)\nprovision_extension <extension> ......... provision extension (provisioning only)\n\n*** JumpBox ***\nprepare_jumpbox ......................... install package on the jumpbox for provisioning\nsync_source_jumpbox ..................... sync source of the jumpbox\nssh_jumpbox ............................. connect to jump box with ssh\nssh_jumpbox_proxy <proxy_port> .......... connect to jump box with ssh and start a socks proxy\n\n*** Providing (Vagrant/Terrafom) ***\nprovide ................................. run only the providing (vagrant/terraform)\n\n*** Provisioning (Ansible) ***\nprovision <playbook> .................... run specific ansible playbook\nprovision_lab ........................... run all the current lab ansible playbooks\nprovision_lab_from <playbook> ........... run all the current lab ansible playbooks from specific playbook to the end\n\n*** Lab Instances ***\ncheck ................................... check dependencies before creation\ninstall ................................. install the current instance (provide + prepare_jumpbox + provision_lab\nset_as_default .......................... set instance as default\nupdate_instance_files ................... update lab instance files\nlist .................................... list lab instances\nload <instance_id> ...................... load a lab instance\n\n*** Configuration ***\nconfig .................................. show current configuration\nunload .................................. unload current instance\ndelete .................................. delete the currently selected lab instance\n```\n\n### status\n\nGive the current lab status\n\n```\nstatus\n```\n\n### start\n\nStart the current lab instance\n\n```\nstart\n```\n\n### stop\n\nStop the current lab instance\n\n```\nstop\n```\n\n### destroy\n\n!!! danger\n    Destroy the current lab instance vms\n\n```\ndestroy\n```\n\n### start_vm\n\nStart a vm\n\n```\nstart_vm <vm_name>\n```\n\n### stop_vm\n\nStop a vm\n\n```\nstop_vm <vm_name>\n```\n\n### restart_vm\n\nRestart a vm (start and stop)\n\n```\nrestart_vm <vm_name>\n```\n\n### destroy_vm\n\n!!! danger\n    Destroy a vm\n\n```\ndestroy_vm <vm_name>\n```\n\n### list_extensions\n\nList available extensions\n\n```\nlist_extensions\n```\n\n### install_extension\n\nAdd an extension to the lab (providing + provisioning)\n\n!!! warning\n    An installed extension can't be deleted\n\n```\ninstall_extension <extension_name>\n```\n\n### provision_extension\n\nLaunch provisioning (ansible) for the extension\n\n```\nprovision_extension <extension_name>\n```\n\n### prepare_jumpbox\n\nPrepare jumpbox : run the preparation script on the jumpbox (install dependencies)\n\n```\nprepare_jumpbox\n```\n\n### sync_source_jumpbox\n\nRsync goad source with the jumpbox\n\n```\nsync_source_jumpbox\n```\n\n### ssh_jumpbox\n\n\nSSH into the jumpbox\n\n```\nssh_jumpbox\n```\n\n### ssh_jumpbox_proxy\n\nSSH into the jumpbox with a socks proxy option (-D)\n\n```\nssh_jumpbox_proxy <socks_proxy_port>\n```\n\n### provide\n\nLaunch providing (machine creation)\n\n```\nprovide\n```\n\n### provision\n\nLaunch specific playbook  (use playbook in ansible/ folder) \n\n```\nprovision <playbook.yml>\n```\n\n### provision_lab\n\nLaunch all the lab provisioning  (install labs on machines with ansible)\n\n```\nprovision_lab\n```\n\n### provision_lab_from\n\nLaunch the lab provisioning from a specific playbook (use playbook in ansible/ folder)\n\n!!! tip\n    useful if the install crash to not redo all the provisioning\n\n```\nprovision_lab_from <playbook.yml>\n```\n\n### check\n\nLaunch the check (same as without instance)\n```\ncheck\n```\n\n### install\n\nLaunch the install (useful if you created an empty instance)\n```\ninstall\n```\n\n### set_as_defualt\n\nSet the current instance as default (automatically loaded on goad start)\n```\nset_as_defualt\n```\n\n### update_instance_files\n\nRecreate the files inside the workspace folder\n```\nupdate_instance_files\n```\n\n### list\n\nList instances\n\n> alias : `ls`\n\n```\nlist\n```\n\n### load\n\nSelect an instance by his name (here change the current instance)\n\n> alias : `use`, `cd`\n\n```\nload <instance name>\n```\n\n### config\n\nShow current configuration\n```\nconfig\n```\n\n### unload\n\nUnload the instance (alias `cd ..`)\n```\nunload\n```\n\n### delete\n\n!!! danger\n    delete the current instance lab and vms\n\n```\ndelete\n```"
  },
  {
    "path": "docs/mkdocs/docs/usage/index.md",
    "content": "# Usage\n\n- Goad script can be run in two ways.\n    - [argument_mode](goad_args.md) : launch goad.sh with arguments to launch one task\n    - [interactive_mode](goad_console.md) : launch an interactive console to manage multiple labs and instances.\n\n- The easy way to use goad is just launch `./goad.sh` and use `?` in the interactive console to get some help.\n"
  },
  {
    "path": "docs/mkdocs/docs/vulnerabilities.md",
    "content": "# Vulnerabilities\n\n[vulnerabilities](./img/diagram-GOAD_compromission_Path_dark.png)"
  },
  {
    "path": "docs/mkdocs/mkdocs.yml",
    "content": "site_name: Game Of Active Directory\nsite_url: https://orange-cyberdefense.github.io/GOAD/\nrepo_url: https://github.com/Orange-Cyberdefense/GOAD\nsite_author: mayfly\nnav:\n  - GOAD: index.md\n  - 🚀 Installation:\n    - index: installation/index.md\n    - Linux: installation/linux.md\n    - Windows: installation/windows.md\n  - 🏗 Providers:\n    - index: providers/index.md\n    - Virtualbox: providers/virtualbox.md\n    - Vmware Workstation: providers/vmware.md\n    - Vmware Esxi: providers/vmware_esxi.md\n    - Aws: providers/aws.md\n    - Azure: providers/azure.md\n    - Proxmox: providers/proxmox.md\n    - Ludus: providers/ludus.md    \n  - 🏰 Labs:\n    - index: labs/index.md\n    - GOAD: labs/GOAD.md\n    - GOAD-Light: labs/GOAD-Light.md\n    - GOAD-Mini: labs/GOAD-Mini.md\n    - NHA: labs/NHA.md\n    - DRACARYS: labs/DRACARYS.md\n    - SCCM: labs/SCCM.md\n    - MINILAB: labs/MINILAB.md\n  - 📈 Extensions:\n    - index: extensions/index.md\n    - guacamole: extensions/guacamole.md\n    - exchange: extensions/exchange.md\n    - lx01: extensions/lx01.md\n    - ws01: extensions/ws01.md\n    - elk: extensions/elk.md\n    - wazuh: extensions/wazuh.md\n  - 💻 Usage: \n    - index : usage/index.md\n    - Arguments: usage/goad_args.md\n    - Interactive: usage/goad_console.md\n  - 📝 Developers: \n    - index : developers/index.md\n    - Add Extension: developers/add_extension.md\n    - Add Lab: developers/add_lab.md\n    - Add Provider: developers/add_provider.md\n  - 🇮 instances: instances.md\n  - 🛠️ provisioning: provisioning.md\n  - ⚠️ Troubleshoot :  troobleshoot.md\n  - ❓ FAQ :  questions.md\n  - 📋 Roadmap :  changelog.md\n  - 📣 References : references.md\n  - 🙏 Thanks :  thx.md\ntheme:\n  name: material\n  logo: assets/logo.png\n  palette:\n    # Palette toggle for dark mode\n    - scheme: slate\n      toggle:\n        icon: material/weather-night\n        name: Switch to light mode\n      primary: black\n      accent: indigo\n    # Palette toggle for light mode\n    - scheme: default\n      toggle:\n        icon: material/weather-sunny\n        name: Switch to dark mode\n      primary: black\n      accent: indigo\n  features:\n#    - navigation.tabs\n    - navigation.indexes\n    - content.tabs.link\nextra_css:\n  - stylesheets/extra.css\n#extra_javascript:\n#  - javascripts/extra.js\nextra:\n  consent:\n    title: Cookie consent\n    description: >- \n      We use cookies to recognize your repeated visits and preferences, as well\n      as to measure the effectiveness of our documentation and whether users\n      find what they're searching for. With your consent, you're helping us to\n      make our documentation better.\n  social:\n    - icon: fontawesome/brands/github\n      link: https://github.com/Orange-Cyberdefense/GOAD\n    - icon: fontawesome/brands/x-twitter\n      link: https://x.com/M4yFly\n    - icon: fontawesome/brands/discord\n      link: https://discord.gg/NYy7rsMf3u\n    - icon: fontawesome/solid/heart\n      link: https://github.com/sponsors/Mayfly277\nmarkdown_extensions:\n  - attr_list\n  - md_in_html\n  - pymdownx.superfences\n  - pymdownx.tabbed:\n      alternate_style: true\n  - pymdownx.tasklist:\n      custom_checkbox: true\n  - admonition\n  - pymdownx.details\n  - pymdownx.superfences\n  - pymdownx.highlight:\n      anchor_linenums: true\n      line_spans: __span\n      pygments_lang_class: true\n  - pymdownx.inlinehilite\n  - pymdownx.snippets\n  - pymdownx.superfences\n  - attr_list\n  - pymdownx.emoji:\n      emoji_index: !!python/name:material.extensions.emoji.twemoji\n      emoji_generator: !!python/name:material.extensions.emoji.to_svg\n"
  },
  {
    "path": "extensions/elk/README.md",
    "content": "# ELK extension\n\n- Extension Name: elk\n- Description: Add an ELK to the current lab\n- Machine name : {{lab_name}}-ELK\n- Compatible with labs : *\n\n## prerequisites\n\nOn ludus prepare template :\n```\nludus templates add -d ubuntu-22.04-x64-server\nludus templates build\n```\n\n## Install\n\n```\ninstance_id> install_extension elk\n```\n\n- machine: {{lab_name}}-ELK\n- filebeat agent domain computer machines\n\n\n## Uninstall\n\n- Not implemented yet\n"
  },
  {
    "path": "extensions/elk/ansible/install.yml",
    "content": "# LOGS and Monitoring ==========================================================================================\n- name: Install ELK\n  hosts: elk_server\n  become: yes\n  roles:\n    - { role: 'elk', tags: 'elk' }\n\n- name: Install log agent on windows vms\n  hosts: elk_log\n  roles:\n    - { role: 'logs_windows', tags: 'agent' }\n"
  },
  {
    "path": "extensions/elk/ansible/roles/elk/defaults/main.yml",
    "content": "elasticsearch_version: '7.x'\nes_cluster_name: elasticsearch"
  },
  {
    "path": "extensions/elk/ansible/roles/elk/files/elasticsearch.yml",
    "content": "# ======================== Elasticsearch Configuration =========================\n#\n# NOTE: Elasticsearch comes with reasonable defaults for most settings.\n#       Before you set out to tweak and tune the configuration, make sure you\n#       understand what are you trying to accomplish and the consequences.\n#\n# The primary way of configuring a node is via this file. This template lists\n# the most important settings you may want to configure for a production cluster.\n#\n# Please consult the documentation for further information on configuration options:\n# https://www.elastic.co/guide/en/elasticsearch/reference/index.html\n#\n# ---------------------------------- Cluster -----------------------------------\n#\n# Use a descriptive name for your cluster:\n#\n#cluster.name: my-application\n#\n# ------------------------------------ Node ------------------------------------\n#\n# Use a descriptive name for the node:\n#\n#node.name: node-1\n#\n# Add custom attributes to the node:\n#\n#node.attr.rack: r1\n#\n# ----------------------------------- Paths ------------------------------------\n#\n# Path to directory where to store the data (separate multiple locations by comma):\n#\npath.data: /var/lib/elasticsearch\n#\n# Path to log files:\n#\npath.logs: /var/log/elasticsearch\n#\n# ----------------------------------- Memory -----------------------------------\n#\n# Lock the memory on startup:\n#\n#bootstrap.memory_lock: true\n#\n# Make sure that the heap size is set to about half the memory available\n# on the system and that the owner of the process is allowed to use this\n# limit.\n#\n# Elasticsearch performs poorly when the system is swapping the memory.\n#\n# ---------------------------------- Network -----------------------------------\n#\n# Set the bind address to a specific IP (IPv4 or IPv6):\n#\nnetwork.host: 0.0.0.0\n#\n# Set a custom port for HTTP:\n#\nhttp.port: 9200\n#\n# For more information, consult the network module documentation.\n#\n# --------------------------------- Discovery ----------------------------------\n#\n# Pass an initial list of hosts to perform discovery when this node is started:\n# The default list of hosts is [\"127.0.0.1\", \"[::1]\"]\n#\n#discovery.seed_hosts: [\"host1\", \"host2\"]\ndiscovery.type: single-node\n#\n# Bootstrap the cluster using an initial set of master-eligible nodes:\n#\n#cluster.initial_master_nodes: [\"node-1\", \"node-2\"]\n#\n# For more information, consult the discovery and cluster formation module documentation.\n#\n# ---------------------------------- Gateway -----------------------------------\n#\n# Block initial recovery after a full cluster restart until N nodes are started:\n#\n#gateway.recover_after_nodes: 3\n#\n# For more information, consult the gateway module documentation.\n#\n# ---------------------------------- Various -----------------------------------\n#\n# Require explicit names when deleting indices:\n#\n#action.destructive_requires_name: true\n"
  },
  {
    "path": "extensions/elk/ansible/roles/elk/files/kibana.yml",
    "content": "# Kibana is served by a back end server. This setting specifies the port to use.\nserver.port: 5601\n\n# Specifies the address to which the Kibana server will bind. IP addresses and host names are both valid values.\n# The default is 'localhost', which usually means remote machines will not be able to connect.\n# To allow connections from remote users, set this parameter to a non-loopback address.\nserver.host: \"0.0.0.0\"\n\n# Enables you to specify a path to mount Kibana at if you are running behind a proxy.\n# Use the `server.rewriteBasePath` setting to tell Kibana if it should remove the basePath\n# from requests it receives, and to prevent a deprecation warning at startup.\n# This setting cannot end in a slash.\n#server.basePath: \"\"\n\n# Specifies whether Kibana should rewrite requests that are prefixed with\n# `server.basePath` or require that they are rewritten by your reverse proxy.\n# This setting was effectively always `false` before Kibana 6.3 and will\n# default to `true` starting in Kibana 7.0.\n#server.rewriteBasePath: false\n\n# Specifies the public URL at which Kibana is available for end users. If\n# `server.basePath` is configured this URL should end with the same basePath.\n#server.publicBaseUrl: \"\"\n\n# The maximum payload size in bytes for incoming server requests.\n#server.maxPayloadBytes: 1048576\n\n# The Kibana server's name.  This is used for display purposes.\n#server.name: \"your-hostname\"\n\n# The URLs of the Elasticsearch instances to use for all your queries.\n#elasticsearch.hosts: [\"http://localhost:9200\"]\n\n# Kibana uses an index in Elasticsearch to store saved searches, visualizations and\n# dashboards. Kibana creates a new index if the index doesn't already exist.\n#kibana.index: \".kibana\"\n\n# The default application to load.\n#kibana.defaultAppId: \"home\"\n\n# If your Elasticsearch is protected with basic authentication, these settings provide\n# the username and password that the Kibana server uses to perform maintenance on the Kibana\n# index at startup. Your Kibana users still need to authenticate with Elasticsearch, which\n# is proxied through the Kibana server.\n#elasticsearch.username: \"kibana_system\"\n#elasticsearch.password: \"pass\"\n\n# Enables SSL and paths to the PEM-format SSL certificate and SSL key files, respectively.\n# These settings enable SSL for outgoing requests from the Kibana server to the browser.\n#server.ssl.enabled: false\n#server.ssl.certificate: /path/to/your/server.crt\n#server.ssl.key: /path/to/your/server.key\n\n# Optional settings that provide the paths to the PEM-format SSL certificate and key files.\n# These files are used to verify the identity of Kibana to Elasticsearch and are required when\n# xpack.security.http.ssl.client_authentication in Elasticsearch is set to required.\n#elasticsearch.ssl.certificate: /path/to/your/client.crt\n#elasticsearch.ssl.key: /path/to/your/client.key\n\n# Optional setting that enables you to specify a path to the PEM file for the certificate\n# authority for your Elasticsearch instance.\n#elasticsearch.ssl.certificateAuthorities: [ \"/path/to/your/CA.pem\" ]\n\n# To disregard the validity of SSL certificates, change this setting's value to 'none'.\n#elasticsearch.ssl.verificationMode: full\n\n# Time in milliseconds to wait for Elasticsearch to respond to pings. Defaults to the value of\n# the elasticsearch.requestTimeout setting.\n#elasticsearch.pingTimeout: 1500\n\n# Time in milliseconds to wait for responses from the back end or Elasticsearch. This value\n# must be a positive integer.\n#elasticsearch.requestTimeout: 30000\n\n# List of Kibana client-side headers to send to Elasticsearch. To send *no* client-side\n# headers, set this value to [] (an empty list).\n#elasticsearch.requestHeadersWhitelist: [ authorization ]\n\n# Header names and values that are sent to Elasticsearch. Any custom headers cannot be overwritten\n# by client-side headers, regardless of the elasticsearch.requestHeadersWhitelist configuration.\n#elasticsearch.customHeaders: {}\n\n# Time in milliseconds for Elasticsearch to wait for responses from shards. Set to 0 to disable.\n#elasticsearch.shardTimeout: 30000\n\n# Logs queries sent to Elasticsearch. Requires logging.verbose set to true.\n#elasticsearch.logQueries: false\n\n# Specifies the path where Kibana creates the process ID file.\n#pid.file: /run/kibana/kibana.pid\n\n# Enables you to specify a file where Kibana stores log output.\n#logging.dest: stdout\n\n# Set the value of this setting to true to suppress all logging output.\n#logging.silent: false\n\n# Set the value of this setting to true to suppress all logging output other than error messages.\n#logging.quiet: false\n\n# Set the value of this setting to true to log all events, including system usage information\n# and all requests.\n#logging.verbose: false\n\n# Set the interval in milliseconds to sample system and process performance\n# metrics. Minimum is 100ms. Defaults to 5000.\n#ops.interval: 5000\n\n# Specifies locale to be used for all localizable strings, dates and number formats.\n# Supported languages are the following: English - en , by default , Chinese - zh-CN .\n#i18n.locale: \"en\"\n"
  },
  {
    "path": "extensions/elk/ansible/roles/elk/tasks/main.yml",
    "content": "- name: \"Update cache\"\n  apt:\n    update_cache: true\n    cache_valid_time: 86400\n\n- name: Add required dependencies.\n  apt:\n    name:\n      - apt-transport-https\n      - gnupg2\n    state: present\n    update_cache: yes\n\n- name: Add Elasticsearch apt key.\n  apt_key:\n    url: https://artifacts.elastic.co/GPG-KEY-elasticsearch\n    state: present\n\n- name: Add Elasticsearch repository.\n  apt_repository:\n    repo: 'deb https://artifacts.elastic.co/packages/{{ elasticsearch_version }}/apt stable main'\n    state: present\n    update_cache: true\n\n- name: Install logstash\n  apt:\n    name: logstash\n    state: present\n\n- name: Install java\n  apt:\n    name: openjdk-11-jre\n    state: present\n\n- name: Install elasticsearch\n  apt:\n    name: elasticsearch\n    state: present\n\n- name: Install kibana\n  apt:\n    name: kibana\n    state: present\n\n- name: copy kibana config\n  copy:\n    src: kibana.yml\n    dest: /etc/kibana/kibana.yml\n    owner: \"root\"\n    group: \"kibana\"\n    mode: 0660\n\n- name: elasticsearch change start timeout to 3min\n  lineinfile:\n    destfile: /usr/lib/systemd/system/elasticsearch.service\n    regexp: 'TimeoutStartSec='\n    line: 'TimeoutStartSec=180'\n\n- name: copy elasticsearch config\n  copy:\n    src: elasticsearch.yml\n    dest: /etc/elasticsearch/elasticsearch.yml\n    owner: \"root\"\n    group: \"elasticsearch\"\n    mode: 0660\n\n- name: enable logstash\n  service:\n    name: logstash\n    enabled: yes\n\n- name: enable elasticsearch\n  service:\n    name: elasticsearch\n    enabled: yes\n\n- name: enable kibana\n  service:\n    name: kibana\n    enabled: yes\n\n- name: start logstash\n  service:\n    name: logstash\n    state: started\n\n- name: start elasticsearch\n  service:\n    name: elasticsearch\n    state: started\n\n- name: start kibana\n  service:\n    name: kibana\n    state: started\n"
  },
  {
    "path": "extensions/elk/ansible/roles/logs_windows/defaults/main.yml",
    "content": "\nsysmon_download_url_base: \"https://download.sysinternals.com/files\"\nsysmon_install_location: \"c:\\\\sysmon\"\nsysmon_download_file: Sysmon\nfile_ext: .zip\nsysmon_config_url: \"https://raw.githubusercontent.com/SwiftOnSecurity/sysmon-config/master/sysmonconfig-export.xml\"\n\nwinlogbeat_service:\n  install_path_64: \"C:\\\\Program Files\\\\Elastic\\\\winlogbeat\"\n  install_path_32: \"C:\\\\Program Files (x86)\\\\Elastic\\\\winlogbeat\"\n  version: \"7.17.6\"\n  download: true"
  },
  {
    "path": "extensions/elk/ansible/roles/logs_windows/files/sysmonconfig-export.xml",
    "content": "﻿<!--\n  sysmon-config | A Sysmon configuration focused on default high-quality event tracing and easy customization by the community\n  Source version:\t74 | Date: 2021-07-08\n  Source project:\thttps://github.com/SwiftOnSecurity/sysmon-config\n  Source license:\tCreative Commons Attribution 4.0 | You may privatize, fork, edit, teach, publish, or deploy for commercial use - with attribution in the text.\n\n  Fork version:\t<N/A>\n  Fork author:\t<N/A>\n  Fork project:\t<N/A>\n  Fork license:\t<N/A>\n\n  REQUIRED: Sysmon version 13 or higher (due to changes in syntax and bug-fixes)\n\thttps://docs.microsoft.com/en-us/sysinternals/downloads/sysmon\n\n  NOTE: To collect Sysmon logs centrally for free, see https://aka.ms/WEF | Command to allow log access to the Network Service:\n\twevtutil.exe sl Microsoft-Windows-Sysmon/Operational /ca:O:BAG:SYD:(A;;0xf0005;;;SY)(A;;0x5;;;BA)(A;;0x1;;;S-1-5-32-573)(A;;0x1;;;NS)\n\n  NOTE: Do not let the size and complexity of this configuration discourage you from customizing it or building your own.\n\tThis configuration is based around known, high-signal event tracing, and thus appears complicated, but it is only very\n\tdetailed. Significant effort over years has been invested in front-loading as much filtering as possible onto the\n\tclient. This is to make analysis of intrusions possible by hand, and to try to surface anomalous activity as quickly\n\tas possible to technicians armed only with Event Viewer. Its purpose is to democratize system monitoring for all organizations.\n\n  NOTE: Sysmon is NOT a whitelist solution or HIDS correlation engine, it is a computer change logging tool.\n\tDo NOT ignore everything possible. Sysmon's purpose is providing context during a threat or problem investigation. Legitimate\n\tprocesses are routinely used by threats - do not blindly exclude them. Additionally, be mindful of process-hollowing / imitation.\n\n  NOTE: By default this monitors DNS, which is extremely noisy. If you are starting out on your monitoring journey, just remove that section.\n\tYou can remove DNS events from Event Viewer screen by applying a 'Filter Current View' for event IDs of: -22\n\tAdditionally, if you want to monitor DNS, you should deploy client-side adblocking to reduce lookups. See the DNS section for info.\n\n  NOTE: This configuration is designed for PER-MACHINE installs of Chrome and OneDrive. That moves their binaries out of user-controlled folders.\n\tOtherwise, attackers could imitate these common applications, and bypass your logging. Below are silent upgrades you can do, no user impact:\n\t- https://docs.microsoft.com/en-us/onedrive/per-machine-installation\n\t- https://cloud.google.com/chrome-enterprise/browser/download/\n\t- As of 2021-02-16 there is no machine-level version of Microsoft Teams. The one provided copies itself to the user profile.\n\n  NOTE: Sysmon is not hardened against an attacker with admin rights. Additionally, this configuration offers an attacker, willing\n\tto study it, limited ways to evade some of the logging. If you are in a very high-threat environment, you should consider a broader,\n\tlog-most approach. However, in the vast majority of cases, an attacker will bumble through multiple behavioral traps which\n\tthis configuration monitors, especially in the first minutes.\n\n  NOTE: If you encounter unexplainable event inclusion/exclusion, you may have a second Sysmon instance installed under a different exe filename.\n\tTo clear this, try downloading the latest version and uninstalling with -u force. If it hangs, kill the processes and run it again to cleanup.\n\n  TECHNICAL:\n  - Run sysmon.exe -? for a briefing on Sysmon configuration.\n  - Sysmon XML cannot use the AMPERSAND sign. Replace it with this: &amp;\n  - Sysmon 8+ can track which rule caused an event to be logged through the \"RuleName\" field.\n  - If you only specify exclude for a filtering subsection, everything in that subsection is logged by default.\n  - Some Sysmon monitoring abilities are not meant for widely deployed general-purpose use due to performance impact. Depends on environment.\n  - Duplicate or overlapping \"Include\" rules do not result in duplicate events being logged.\n  - All characters enclosed by XML tags are always interpreted literally. Sysmon does not support wildcards (*), alternate characters, or RegEx.\n  - In registry events, the value name is appended to the full key path with a \"\\\" delimiter. Default key values are named \"\\(Default)\"\n  - \"Image\" is a technical term for a compiled binary file like an EXE or DLL. Also, it can match just the filename, or entire path.\n  - \"ProcessGuid\" and \"LoginGuid\" are not random, they contain some embedded information. https://gist.github.com/mattifestation/0102042160c9a60b2b847378c0ef70b4\n\n  FILTERING: Filter conditions available for use are: is,is not,contains,contains any,contains all,excludes,excludes any,excludes all,begin with,end with,less than,more than,image\n  - The \"image\" filter is usable on any field. Same as \"is\" but can either match entire string, or only the text after last \"\\\". Credit: @mattifestation\n\n-->\n\n<Sysmon schemaversion=\"4.50\">\n\t<!--SYSMON META CONFIG-->\n\t<HashAlgorithms>md5,sha256,IMPHASH</HashAlgorithms> <!-- Both MD5 and SHA256 are the industry-standard algorithms. Remove IMPHASH if you do not use DLL import fingerprinting. -->\n\t<CheckRevocation/> <!-- Check loaded drivers, log if their code-signing certificate has been revoked, in case malware stole one to sign a kernel driver -->\n\n\t<!-- <ImageLoad/> --> <!-- Would manually force-on ImageLoad monitoring, even without configuration below. Included only documentation. -->\n\t<!-- <ProcessAccessConfig/> --> <!-- Would manually force-on ProcessAccess monitoring, even without configuration below. Included only documentation. -->\n\t<!-- <PipeMonitoringConfig/> --> <!-- Would manually force-on PipeCreated / PipeConnected events, even without configuration below. Included only documentation. -->\n\t<!-- <ArchiveDirectory> -->\n\n\t<EventFiltering>\n\n\t<!--SYSMON EVENT ID 1 : PROCESS CREATION [ProcessCreate]-->\n\t\t<!--COMMENT:\tAll processes launched will be logged, except for what matches a rule below. It's best to be as specific as possible,\n\t\t\tto avoid user-mode executables imitating other process names to avoid logging, or if malware drops files in an existing directory.\n\t\t\tUltimately, you must weigh CPU time checking many detailed rules, against the risk of malware exploiting the blindness created.\n\t\t\tBeware of Masquerading, where attackers imitate the names and paths of legitimate tools. Ideally, you'd use both file path and\n\t\t\tcode signatures to validate, but Sysmon does not support that. Look into AppLocker/WindowsDeviceGuard for whitelisting support. -->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessID, Image, FileVersion, Description, Product, Company, CommandLine, CurrentDirectory, User, LogonGuid, LogonId, TerminalSessionId, IntegrityLevel, Hashes, ParentProcessGuid, ParentProcessId, ParentImage, ParentCommandLine, RuleName-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ProcessCreate onmatch=\"exclude\">\n\t\t\t<!--SECTION: Microsoft Windows-->\n\t\t\t<CommandLine condition=\"begin with\"> \"C:\\Windows\\system32\\wermgr.exe\" \"-queuereporting_svc\" </CommandLine> <!--Windows:Windows error reporting/telemetry-->\n\t\t\t<CommandLine condition=\"begin with\">C:\\Windows\\system32\\DllHost.exe /Processid</CommandLine> <!--Windows-->\n\t\t\t<CommandLine condition=\"begin with\">C:\\Windows\\system32\\wbem\\wmiprvse.exe -Embedding</CommandLine> <!--Windows: WMI provider host-->\n\t\t\t<CommandLine condition=\"begin with\">C:\\Windows\\system32\\wbem\\wmiprvse.exe -secured -Embedding</CommandLine> <!--Windows: WMI provider host-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\wermgr.exe -upload</CommandLine> <!--Windows:Windows error reporting/telemetry-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\SearchIndexer.exe /Embedding</CommandLine> <!--Windows: Search Indexer-->\n\t\t\t<CommandLine condition=\"is\">C:\\windows\\system32\\wermgr.exe -queuereporting</CommandLine> <!--Windows:Windows error reporting/telemetry-->\n\t\t\t<CommandLine condition=\"is\">\\??\\C:\\Windows\\system32\\autochk.exe *</CommandLine> <!--Microsoft:Bootup: Auto Check Utility-->\n\t\t\t<CommandLine condition=\"is\">\\SystemRoot\\System32\\smss.exe</CommandLine> <!--Microsoft:Bootup: Windows Session Manager-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\RuntimeBroker.exe -Embedding</CommandLine> <!--Windows:Apps permissions [ https://fossbytes.com/runtime-broker-process-windows-10/ ] -->\n\t\t\t<Image condition=\"is\">C:\\Program Files (x86)\\Common Files\\microsoft shared\\ink\\TabTip32.exe</Image> <!--Windows: Touch Keyboard and Handwriting Panel Helper-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\System32\\TokenBrokerCookies.exe</Image> <!--Windows: SSO sign-in assistant for MicrosoftOnline.com-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\System32\\plasrv.exe</Image> <!--Windows: Performance Logs and Alerts DCOM Server-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\System32\\wifitask.exe</Image> <!--Windows: Wireless Background Task-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\CompatTelRunner.exe</Image> <!--Windows: Customer Experience Improvement-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\PrintIsolationHost.exe</Image> <!--Windows: Printing-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\SppExtComObj.Exe</Image> <!--Windows: KMS activation-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\audiodg.exe</Image> <!--Windows: Launched constantly-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\conhost.exe</Image> <!--Windows: Command line interface host process-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\mobsync.exe</Image> <!--Windows: Network file syncing-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\musNotification.exe</Image> <!--Windows: Update pop-ups-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\musNotificationUx.exe</Image> <!--Windows: Update pop-ups-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\powercfg.exe</Image> <!--Microsoft:Power configuration management-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\sndVol.exe</Image> <!--Windows: Volume control-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\sppsvc.exe</Image> <!--Windows: Software Protection Service-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\wbem\\WmiApSrv.exe</Image> <!--Windows: WMI performance adapter host process-->\n\t\t\t<IntegrityLevel condition=\"is\">AppContainer</IntegrityLevel> <!--Windows: Don't care about sandboxed processes right now. Will need to revisit this decision.-->\n\t\t\t<ParentCommandLine condition=\"begin with\">%%SystemRoot%%\\system32\\csrss.exe ObjectDirectory=\\Windows</ParentCommandLine> <!--Windows:CommandShell: Triggered when programs use the command shell, but doesn't provide attribution for what caused it-->\n\t\t\t<ParentCommandLine condition=\"is\">C:\\windows\\system32\\wermgr.exe -queuereporting</ParentCommandLine> <!--Windows:Windows error reporting/telemetry-->\n\t\t\t<CommandLine condition=\"is\">C:\\WINDOWS\\system32\\devicecensus.exe UserCxt</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\usocoreworker.exe -Embedding</CommandLine>\n\t\t\t<ParentImage condition=\"is\">C:\\Windows\\system32\\SearchIndexer.exe</ParentImage> <!--Windows:Search: Launches many uninteresting sub-processes-->\n\t\t\t<!--SECTION: Windows:svchost-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k appmodel -s StateRepository</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k appmodel -p -s camsvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k appmodel</CommandLine> <!--Windows 10-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k appmodel -p -s tiledatamodelsvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k camera -s FrameServer</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k dcomlaunch -s LSM</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k dcomlaunch -s PlugPlay</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k defragsvc</CommandLine> <!--Windows defragmentation-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k devicesflow -s DevicesFlowUserSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k imgsvc</CommandLine> <!--Microsoft:The Windows Image Acquisition Service-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localService -s EventSystem</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localService -s bthserv</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k LocalService -p -s BthAvctpSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localService -s nsi</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localService -s w32Time</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceAndNoImpersonation</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted -s Dhcp</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted -s EventLog</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted -s TimeBrokerSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted -s WFDSConMgrSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k LocalServiceNetworkRestricted -s BTAGService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\svchost.exe -k LocalSystemNetworkRestricted -p -s NcbService</CommandLine> <!--Win10:1903:Network Connection Broker-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceAndNoImpersonation -s SensrSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceAndNoImpersonation -p -s SSDPSRV</CommandLine> <!--Windows:SSDP [ https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNoNetwork</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -p -s WPDBusEnum</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -p -s fhsvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s DeviceAssociationService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s NcbService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s SensorService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s TabletInputService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s UmRdpService</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s WPDBusEnum</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -p -s NgcSvc</CommandLine> <!--Microsoft:Passport--> \n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceNetworkRestricted -p -s NgcCtnrSvc</CommandLine> <!--Microsoft:Passport Container--> \n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localServiceAndNoImpersonation -s SCardSvr</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -p -s wuauserv</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\svchost.exe -k netsvcs -p -s SessionEnv</CommandLine> <!--Windows:Remote desktop configuration-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted -s WdiSystemHost</CommandLine> <!--Windows: Diagnostic System Host [ http://www.blackviper.com/windows-services/diagnostic-system-host/ ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\svchost.exe -k localSystemNetworkRestricted -p -s WdiSystemHost</CommandLine> <!--Windows: Diagnostic System Host [ http://www.blackviper.com/windows-services/diagnostic-system-host/ ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted</CommandLine> <!--Windows-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -p -s wlidsvc</CommandLine> <!--Windows: Windows Live Sign-In Assistant [ https://www.howtogeek.com/howto/30348/what-are-wlidsvc.exe-and-wlidsvcm.exe-and-why-are-they-running/ ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -p -s ncaSvc</CommandLine> <!--Windows: Network Connectivity Assistant [ http://www.blackviper.com/windows-services/network-connectivity-assistant/ ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s BDESVC</CommandLine> <!--Windows:Network: BitLocker Drive Encryption-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\svchost.exe -k netsvcs -p -s BDESVC</CommandLine> <!--Microsoft:Win10:1903:Network: BitLocker Drive Encryption-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -p -s BITS</CommandLine> <!--Windows:Network: Background Intelligent File Transfer (BITS) -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s BITS</CommandLine> <!--Windows:Network: Background Intelligent File Transfer (BITS) -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s CertPropSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s DsmSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -p -s Appinfo</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s Gpsvc</CommandLine> <!--Windows:Network: Group Policy -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s ProfSvc</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s SENS</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s SessionEnv</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s Themes</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs -s Winmgmt</CommandLine> <!--Windows: Windows Management Instrumentation (WMI) -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService -p -s DoSvc</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService -s Dnscache</CommandLine> <!--Windows:Network: DNS caching, other uses -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService -s LanmanWorkstation</CommandLine> <!--Windows:Network: \"Workstation\" service, used for SMB file-sharing connections and RDP-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService -s NlaSvc</CommandLine> <!--Windows:Network: Network Location Awareness-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService -s TermService</CommandLine> <!--Windows:Network: Terminal Services (RDP)-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkService</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k networkServiceNetworkRestricted</CommandLine> <!--Windows: Network services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k rPCSS</CommandLine> <!--Windows Services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k secsvcs</CommandLine>\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k swprv</CommandLine> <!--Microsoft:Software Shadow Copy Provider-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k unistackSvcGroup</CommandLine> <!--Windows 10-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k utcsvc</CommandLine> <!--Windows Services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k wbioSvcGroup</CommandLine> <!--Windows Services-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k werSvcGroup</CommandLine> <!--Windows: ErrorReporting-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k wusvcs -p -s WaaSMedicSvc</CommandLine> <!--Windows: Update Medic Service [ https://www.thewindowsclub.com/windows-update-medic-service ] -->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\System32\\svchost.exe -k wsappx -p -s ClipSVC</CommandLine> <!--Windows:Apps: Client License Service-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k wsappx -p -s AppXSvc</CommandLine> <!--Windows:Apps: AppX Deployment Service-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k wsappx -s ClipSVC</CommandLine> <!--Windows:Apps: Client License Service-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k wsappx</CommandLine> <!--Windows:Apps [ https://www.howtogeek.com/320261/what-is-wsappx-and-why-is-it-running-on-my-pc/ ] -->\n\t\t\t<ParentCommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k netsvcs</ParentCommandLine> <!--Windows: Network services: Spawns Consent.exe-->\n\t\t\t<ParentCommandLine condition=\"is\">C:\\Windows\\system32\\svchost.exe -k localSystemNetworkRestricted</ParentCommandLine> <!--Windows-->\n\t\t\t<CommandLine condition=\"is\">C:\\Windows\\system32\\deviceenroller.exe /c /AutoEnrollMDM</CommandLine> <!--Windows: AzureAD device enrollment agent-->\n\t\t\t<!--SECTION: Microsoft:Edge-->\n\t\t\t<CommandLine condition=\"begin with\">\"C:\\Program Files (x86)\\Microsoft\\Edge Dev\\Application\\msedge.exe\" --type=</CommandLine>\n\t\t\t<!--SECTION: Microsoft:dotNet-->\n\t\t\t<CommandLine condition=\"begin with\">C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\ngen.exe</CommandLine> <!--Microsoft:DotNet-->\n\t\t\t<CommandLine condition=\"begin with\">C:\\WINDOWS\\Microsoft.NET\\Framework64\\v4.0.30319\\Ngen.exe</CommandLine> <!--Microsoft:DotNet-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\mscorsvw.exe</Image> <!--Microsoft:DotNet-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\mscorsvw.exe</Image> <!--Microsoft:DotNet-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\Microsoft.Net\\Framework64\\v3.0\\WPF\\PresentationFontCache.exe</Image> <!--Windows: Font cache service-->\n\t\t\t<ParentCommandLine condition=\"contains\">C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\ngentask.exe</ParentCommandLine>\n\t\t\t<ParentImage condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\mscorsvw.exe</ParentImage> <!--Microsoft:DotNet-->\n\t\t\t<ParentImage condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\ngentask.exe</ParentImage> <!--Microsoft:DotNet-->\n\t\t\t<ParentImage condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\mscorsvw.exe</ParentImage> <!--Microsoft:DotNet-->\n\t\t\t<ParentImage condition=\"is\">C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\ngentask.exe</ParentImage> <!--Microsoft:DotNet: Spawns thousands of ngen.exe processes-->\n\t\t\t<!--SECTION: Microsoft:Office-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Microsoft Office\\Office16\\MSOSYNC.EXE</Image> <!--Microsoft:Office: Background process for SharePoint/Office365 connectivity-->\n\t\t\t<Image condition=\"is\">C:\\Program Files (x86)\\Microsoft Office\\Office16\\MSOSYNC.EXE</Image> <!--Microsoft:Office: Background process for SharePoint/Office365 connectivity-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Common Files\\Microsoft Shared\\OfficeSoftwareProtectionPlatform\\OSPPSVC.EXE</Image> <!--Microsoft:Office: Licensing service-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Microsoft Office\\Office16\\msoia.exe</Image> <!--Microsoft:Office: Telemetry collector-->\n\t\t\t<Image condition=\"is\">C:\\Program Files (x86)\\Microsoft Office\\root\\Office16\\officebackgroundtaskhandler.exe</Image>\n\t\t\t<!--SECTION: Microsoft:Office:Click2Run-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Common Files\\Microsoft Shared\\ClickToRun\\OfficeC2RClient.exe</Image> <!--Microsoft:Office: Background process-->\n\t\t\t<ParentImage condition=\"is\">C:\\Program Files\\Common Files\\Microsoft Shared\\ClickToRun\\OfficeClickToRun.exe</ParentImage> <!--Microsoft:Office: Background process-->\n\t\t\t<ParentImage condition=\"is\">C:\\Program Files\\Common Files\\Microsoft Shared\\ClickToRun\\OfficeC2RClient.exe</ParentImage> <!--Microsoft:Office: Background process-->\n\t\t\t<!--SECTION: Windows: Media player-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Windows Media Player\\wmpnscfg.exe</Image> <!--Windows: Windows Media Player Network Sharing Service Configuration Application-->\n\t\t\t<!--SECTION: Google-->\n\t\t\t<CommandLine condition=\"begin with\">\"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe\" --type=</CommandLine> <!--Google:Chrome: massive command-line arguments-->\n\t\t\t<CommandLine condition=\"begin with\">\"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --type=</CommandLine> <!--Google:Chrome: massive command-line arguments-->\n\t\t</ProcessCreate>\n\t</RuleGroup>\n\t\n\t<!--SYSMON EVENT ID 2 : FILE CREATION TIME RETROACTIVELY CHANGED IN THE FILESYSTEM [FileCreateTime]-->\n\t\t<!--COMMENT:\t[ https://attack.mitre.org/wiki/Technique/T1099 ] -->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, TargetFilename, CreationUtcTime, PreviousCreationUtcTime-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<FileCreateTime onmatch=\"include\">\n\t\t\t<Image name=\"T1099\" condition=\"begin with\">C:\\Users</Image> <!--Look for timestomping in user area, usually nothing should be doing that here-->\n\t\t\t<TargetFilename name=\"T1099\" condition=\"end with\">.exe</TargetFilename> <!--Look for backdated executables anywhere-->\n\t\t\t<Image name=\"T1099\" condition=\"begin with\">\\Device\\HarddiskVolumeShadowCopy</Image> <!--Nothing should be written here | Credit: @SBousseaden [ https://twitter.com/SBousseaden/status/1133030955407630336 ] -->\n\t\t</FileCreateTime>\n\t</RuleGroup>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<FileCreateTime onmatch=\"exclude\">\n\t\t\t<Image condition=\"image\">OneDrive.exe</Image> <!--OneDrive constantly changes file times-->\n\t\t\t<Image condition=\"image\">C:\\Windows\\system32\\backgroundTaskHost.exe</Image>\n\t\t\t<Image condition=\"contains\">setup</Image> <!--Ignore setups-->\n\t\t\t<Image condition=\"contains\">install</Image> <!--Ignore setups-->\n\t\t\t<Image condition=\"contains\">Update\\</Image> <!--Ignore setups-->\n\t\t\t<Image condition=\"end with\">redist.exe</Image> <!--Ignore setups-->\n\t\t\t<Image condition=\"is\">msiexec.exe</Image> <!--Ignore setups-->\n\t\t\t<Image condition=\"is\">TrustedInstaller.exe</Image> <!--Ignore setups-->\n\t\t\t<TargetFilename condition=\"contains\">\\NVIDIA\\NvBackend\\ApplicationOntology\\</TargetFilename> <!--NVIDIA GeForce Experience Application Ontology, 1000's of events in user profile-->\n\t\t</FileCreateTime>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 3 : NETWORK CONNECTION INITIATED [NetworkConnect]-->\n\t\t<!--COMMENT:\tBy default this configuration takes a very conservative approach to network logging, limited to only extremely high-signal events.-->\n\t\t<!--COMMENT:\t[ https://attack.mitre.org/wiki/Command_and_Control ] [ https://attack.mitre.org/wiki/Exfiltration ] [ https://attack.mitre.org/wiki/Lateral_Movement ] -->\n\t\t<!--TECHNICAL:\tFor the DestinationHostname, Sysmon uses the GetNameInfo API, which will often not have any information, and may just be a CDN. This is NOT reliable for filtering.-->\n\t\t<!--TECHNICAL:\tFor the DestinationPortName, Sysmon uses the GetNameInfo API for the friendly name of ports you see in logs.-->\n\t\t<!--TECHNICAL:\tThese exe do not initiate their connections, and thus includes do not work in this section: BITSADMIN NLTEST-->\n\t\t\n\t\t<!-- https://www.first.org/resources/papers/conf2017/APT-Log-Analysis-Tracking-Attack-Tools-by-Audit-Policy-and-Sysmon.pdf -->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, User, Protocol, Initiated, SourceIsIpv6, SourceIp, SourceHostname, SourcePort, SourcePortName, DestinationIsIpV6, DestinationIp, DestinationHostname, DestinationPort, DestinationPortName-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<NetworkConnect onmatch=\"include\">\n\t\t\t<!--Suspicious sources for network-connecting binaries-->\n\t\t\t<Image name=\"Usermode\" condition=\"begin with\">C:\\Users</Image> <!--Tools downloaded by users can use other processes for networking, but this is a very valuable indicator.-->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">C:\\Recycle</Image> <!--Nothing should operate from the RecycleBin locations.-->\n\t\t\t<Image condition=\"begin with\">C:\\ProgramData</Image> <!--Normally, network communications should be sourced from \"Program Files\" not from ProgramData, something to look at-->\n\t\t\t<Image condition=\"begin with\">C:\\Windows\\Temp</Image> <!--Suspicious anything would communicate from the system-level temp directory-->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">\\</Image> <!--Devices and VSC shouldn't be executing changes | Credit: @SBousseaden @ionstorm @neu5ron @PerchedSystems [ https://twitter.com/SwiftOnSecurity/status/1133167323991486464 ] -->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">C:\\perflogs</Image> <!-- Credit @blu3_team [ https://blu3-team.blogspot.com/2019/05/netconn-from-suspicious-directories.html ] -->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">C:\\intel</Image> <!-- Credit @blu3_team [ https://blu3-team.blogspot.com/2019/05/netconn-from-suspicious-directories.html ] -->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">C:\\Windows\\fonts</Image> <!-- Credit @blu3_team [ https://blu3-team.blogspot.com/2019/05/netconn-from-suspicious-directories.html ] -->\n\t\t\t<Image name=\"Caution\" condition=\"begin with\">C:\\Windows\\system32\\config</Image> <!-- Credit @blu3_team [ https://blu3-team.blogspot.com/2019/05/netconn-from-suspicious-directories.html ] -->\n\t\t\t<!--Suspicious Windows tools-->\n\t\t\t<Image condition=\"image\">at.exe</Image> <!--Windows: Remote task scheduling, removed in Win10 | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">certutil.exe</Image> <!--Windows: Certificate tool can contact outbound | Credit @ion-storm @FVT [ https://twitter.com/FVT/status/834433734602530817 ] -->\n\t\t\t<Image condition=\"image\">cmd.exe</Image> <!--Windows: Remote command prompt-->\n\t\t\t<Image condition=\"image\">cmstp.exe</Image> <!--Windows: Connection manager profiles can launch executables from WebDAV [ https://twitter.com/NickTyrer/status/958450014111633408 ] | Credit @NickTyrer @Oddvarmoe @KyleHanslovan @subTee -->\n\t\t\t<Image condition=\"image\">cscript.exe</Image> <!--WindowsScriptingHost: | Credit @Cyb3rOps [ https://gist.github.com/Neo23x0/a4b4af9481e01e749409 ] -->\n\t\t\t<Image condition=\"image\">driverquery.exe</Image> <!--Windows: Remote recognisance of system configuration, oudated/vulnerable drivers -->\n\t\t\t<Image condition=\"image\">dsquery.exe</Image> <!--Microsoft: Query Active Directory -->\n\t\t\t<Image condition=\"image\">hh.exe</Image> <!--Windows: HTML Help Executable, opens CHM files -->\n\t\t\t<Image condition=\"image\">infDefaultInstall.exe</Image> <!--Microsoft: [ https://github.com/huntresslabs/evading-autoruns ] | Credit @KyleHanslovan -->\n\t\t\t<Image condition=\"image\">java.exe</Image> <!--Java: Monitor usage of vulnerable application and init from JAR files | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">javaw.exe</Image> <!--Java: Monitor usage of vulnerable application and init from JAR files -->\n\t\t\t<Image condition=\"image\">javaws.exe</Image> <!--Java: Monitor usage of vulnerable application and init from JAR files -->\n\t\t\t<Image condition=\"image\">mmc.exe</Image> <!--Windows: -->\n\t\t\t<Image condition=\"image\">msbuild.exe</Image> <!--Windows: [ https://www.hybrid-analysis.com/sample/a314f6106633fba4b70f9d6ddbee452e8f8f44a72117749c21243dc93c7ed3ac?environmentId=100 ] -->\n\t\t\t<Image condition=\"image\">mshta.exe</Image> <!--Windows: HTML application executes scripts without IE protections | Credit @ion-storm [ https://en.wikipedia.org/wiki/HTML_Application ] -->\n\t\t\t<Image condition=\"image\">msiexec.exe</Image> <!--Windows: Can install from http:// paths | Credit @vector-sec -->\n\t\t\t<Image condition=\"image\">nbtstat.exe</Image> <!--Windows: NetBIOS statistics, attackers use to enumerate local network -->\n\t\t\t<Image condition=\"image\">net.exe</Image> <!--Windows: Note - May not detect anything, net.exe is a front-end to lower APIs | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">net1.exe</Image> <!--Windows: Launched by \"net.exe\", but it may not detect connections either -->\n\t\t\t<Image condition=\"image\">notepad.exe</Image> <!--Windows: [ https://secrary.com/ReversingMalware/CoinMiner/ ] [ https://blog.cobaltstrike.com/2013/08/08/why-is-notepad-exe-connecting-to-the-internet/ ] -->\n\t\t\t<Image condition=\"image\">nslookup.exe</Image> <!--Windows: Retrieve data over DNS -->\n\t\t\t<Image condition=\"image\">powershell.exe</Image> <!--Windows: PowerShell interface-->\n\t\t\t<Image condition=\"image\">qprocess.exe</Image> <!--Windows: [ https://www.first.org/resources/papers/conf2017/APT-Log-Analysis-Tracking-Attack-Tools-by-Audit-Policy-and-Sysmon.pdf ] -->\n\t\t\t<Image condition=\"image\">qwinsta.exe</Image> <!--Windows: Query remote sessions | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">qwinsta.exe</Image> <!--Windows: Remotely query login sessions on a server or workstation | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">reg.exe</Image> <!--Windows: Remote Registry editing ability | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">regsvcs.exe</Image> <!--Windows: [ https://www.hybrid-analysis.com/sample/3f94d7080e6c5b8f59eeecc3d44f7e817b31562caeba21d02ad705a0bfc63d67?environmentId=100 ] -->\n\t\t\t<Image condition=\"image\">regsvr32.exe</Image> <!--Windows: [ https://subt0x10.blogspot.com/2016/04/bypass-application-whitelisting-script.html ] -->\n\t\t\t<Image condition=\"image\">rundll32.exe</Image> <!--Windows: [ https://blog.cobaltstrike.com/2016/07/22/why-is-rundll32-exe-connecting-to-the-internet/ ] -->\n\t\t\t<Image condition=\"image\">rwinsta.exe</Image> <!--Windows: Disconnect remote sessions | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">sc.exe</Image> <!--Windows: Remotely change Windows service settings | Credit @ion-storm -->\n\t\t\t<Image condition=\"image\">schtasks.exe</Image> <!--Windows: Command-line interface to local and remote tasks -->\n\t\t\t<Image condition=\"image\">taskkill.exe</Image> <!--Windows: Kill processes, has remote ability -->\n\t\t\t<Image condition=\"image\">tasklist.exe</Image> <!--Windows: List processes, has remote ability -->\n\t\t\t<Image condition=\"image\">wmic.exe</Image> <!--WindowsManagementInstrumentation: Credit @Cyb3rOps [ https://gist.github.com/Neo23x0/a4b4af9481e01e749409 ] -->\n\t\t\t<Image condition=\"image\">wscript.exe</Image> <!--WindowsScriptingHost: | Credit @arekfurt -->\n\t\t\t<!--Relevant 3rd Party Tools-->\n\t\t\t<Image condition=\"image\">nc.exe</Image> <!-- Nmap's modern version of netcat [ https://nmap.org/ncat/guide/index.html#ncat-overview ] [ https://securityblog.gr/1517/create-backdoor-in-windows-with-ncat/ ] -->\n\t\t\t<Image condition=\"image\">ncat.exe</Image> <!-- Nmap's modern version of netcat [ https://nmap.org/ncat/guide/index.html#ncat-overview ] [ https://securityblog.gr/1517/create-backdoor-in-windows-with-ncat/ ] -->\n\t\t\t<Image condition=\"image\">psexec.exe</Image> <!--Sysinternals:PsExec client side | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">psexesvc.exe</Image> <!--Sysinternals:PsExec server side | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">tor.exe</Image> <!--Tor [ https://www.hybrid-analysis.com/sample/800bf028a23440134fc834efc5c1e02cc70f05b2e800bbc285d7c92a4b126b1c?environmentId=100 ] -->\n\t\t\t<Image condition=\"image\">vnc.exe</Image> <!-- VNC client | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">vncservice.exe</Image> <!-- VNC server | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">vncviewer.exe</Image> <!-- VNC client | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">winexesvc.exe</Image> <!-- Winexe service executable | Credit @Cyb3rOps -->\n\t\t\t<Image condition=\"image\">nmap.exe</Image>\n\t\t\t<Image condition=\"image\">psinfo.exe</Image>\n\t\t\t<!--Ports: Suspicious-->\n\t\t\t<DestinationPort name=\"SSH\" condition=\"is\">22</DestinationPort> <!--SSH protocol, monitor admin connections-->\n\t\t\t<DestinationPort name=\"Telnet\" condition=\"is\">23</DestinationPort> <!--Telnet protocol, monitor admin connections, insecure-->\n\t\t\t<DestinationPort name=\"SMTP\" condition=\"is\">25</DestinationPort> <!--SMTP mail protocol port, insecure, used by threats-->\n\t\t\t<DestinationPort name=\"IMAP\" condition=\"is\">143</DestinationPort> <!--IMAP mail protocol port, insecure, used by threats-->\n\t\t\t<DestinationPort name=\"RDP\" condition=\"is\">3389</DestinationPort> <!--Windows:RDP: Monitor admin connections-->\n\t\t\t<DestinationPort name=\"VNC\" condition=\"is\">5800</DestinationPort> <!--VNC protocol: Monitor admin connections, often insecure, using hard-coded admin password-->\n\t\t\t<DestinationPort name=\"VNC\" condition=\"is\">5900</DestinationPort> <!--VNC protocol Monitor admin connections, often insecure, using hard-coded admin password-->\n\t\t\t<DestinationPort name=\"Alert,Metasploit\" condition=\"is\">444</DestinationPort>\n\t\t\t<!--Ports: Proxy-->\n\t\t\t<DestinationPort name=\"Proxy\" condition=\"is\">1080</DestinationPort> <!--Socks proxy port | Credit @ion-storm-->\n\t\t\t<DestinationPort name=\"Proxy\" condition=\"is\">3128</DestinationPort> <!--Socks proxy port | Credit @ion-storm-->\n\t\t\t<DestinationPort name=\"Proxy\" condition=\"is\">8080</DestinationPort> <!--Socks proxy port | Credit @ion-storm-->\n\t\t\t<!--Ports: Tor-->\n\t\t\t<DestinationPort name=\"Tor\" condition=\"is\">1723</DestinationPort> <!--Tor protocol [ https://attack.mitre.org/wiki/Technique/T1090 ] | Credit @ion-storm-->\n\t\t\t<DestinationPort name=\"Tor\" condition=\"is\">9001</DestinationPort> <!--Tor protocol [ http://www.computerworlduk.com/tutorial/security/tor-enterprise-2016-blocking-malware-darknet-use-rogue-nodes-3633907/ ] -->\n\t\t\t<DestinationPort name=\"Tor\" condition=\"is\">9030</DestinationPort> <!--Tor protocol [ http://www.computerworlduk.com/tutorial/security/tor-enterprise-2016-blocking-malware-darknet-use-rogue-nodes-3633907/ ] -->\n\t\t</NetworkConnect>\n\t</RuleGroup>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<NetworkConnect onmatch=\"exclude\">\n\t\t\t<!--SECTION: Microsoft-->\n\t\t\t<Image condition=\"begin with\">C:\\ProgramData\\Microsoft\\Windows Defender\\Platform\\</Image>\n\t\t\t<Image condition=\"end with\">AppData\\Local\\Microsoft\\Teams\\current\\Teams.exe</Image> <!--Microsoft: Teams-->\n\t\t\t<DestinationHostname condition=\"end with\">.microsoft.com</DestinationHostname> <!--Microsoft:Update delivery-->\n\t\t\t<DestinationHostname condition=\"end with\">microsoft.com.akadns.net</DestinationHostname> <!--Microsoft:Update delivery-->\n\t\t\t<DestinationHostname condition=\"end with\">microsoft.com.nsatc.net</DestinationHostname> <!--Microsoft:Update delivery-->\n\t\t\t<!--OCSP known addresses-->\n\t\t\t<DestinationIp condition=\"is\">23.4.43.27</DestinationIp> <!--Digicert [ https://otx.alienvault.com/indicator/ip/23.4.43.27 ] -->\n\t\t\t<DestinationIp condition=\"is\">72.21.91.29</DestinationIp> <!--Digicert [ https://otx.alienvault.com/indicator/ip/72.21.91.29 ] -->\n\t\t\t<!--Section: Loopback Addresses-->\n\t\t\t<DestinationIp condition=\"is\">127.0.0.1</DestinationIp> <!--Credit @ITProPaul-->\n\t\t\t<DestinationIp condition=\"begin with\">fe80:0:0:0</DestinationIp> <!--Credit @ITProPaul-->\n\t\t</NetworkConnect>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 4 : RESERVED FOR SYSMON SERVICE STATUS MESSAGES-->\n\n\t\t<!--DATA: UtcTime, State, Version, SchemaVersion-->\n\t\t<!--Cannot be filtered.-->\n\n\t<!--SYSMON EVENT ID 5 : PROCESS ENDED [ProcessTerminate]-->\n\t\t<!--COMMENT:\tUseful data in building infection timelines.-->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ProcessTerminate onmatch=\"include\">\n\t\t\t<Image condition=\"begin with\">C:\\Users</Image> <!--Process terminations by user binaries-->\n\t\t\t<Image condition=\"begin with\">\\</Image> <!--Devices and VSC shouldn't be executing changes | Credit: @SBousseaden @ionstorm @neu5ron @PerchedSystems [ https://twitter.com/SwiftOnSecurity/status/1133167323991486464 ] -->\n\t\t</ProcessTerminate>\n\t</RuleGroup>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ProcessTerminate onmatch=\"exclude\">\n\t\t</ProcessTerminate>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 6 : DRIVER LOADED INTO KERNEL [DriverLoad]-->\n\t\t<!--COMMENT:\tBecause drivers with bugs can be used to escalate to kernel permissions, be extremely selective\n\t\t\tabout what you exclude from monitoring. Low event volume, little incentive to exclude.\n\t\t\t[ https://attack.mitre.org/wiki/Technique/T1014 ] -->\n\t\t<!--TECHNICAL:\tSysmon will check the signing certificate revocation status of any driver you don't exclude.-->\n\n\t\t<!--DATA: UtcTime, ImageLoaded, Hashes, Signed, Signature, SignatureStatus-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<DriverLoad onmatch=\"exclude\">\n\t\t\t<Signature condition=\"contains\">microsoft</Signature> <!--Exclude signed Microsoft drivers-->\n\t\t\t<Signature condition=\"contains\">windows</Signature> <!--Exclude signed Microsoft drivers-->\n\t\t\t<Signature condition=\"begin with\">Intel </Signature> <!--Exclude signed Intel drivers-->\n\t\t</DriverLoad>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 7 : DLL (IMAGE) LOADED BY PROCESS [ImageLoad]-->\n\t\t<!--COMMENT:\tCan cause high system load, disabled by default.-->\n\t\t<!--COMMENT:\t[ https://attack.mitre.org/wiki/Technique/T1073 ] [ https://attack.mitre.org/wiki/Technique/T1038 ] [ https://attack.mitre.org/wiki/Technique/T1034 ] -->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, ImageLoaded, Hashes, Signed, Signature, SignatureStatus-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ImageLoad onmatch=\"include\">\n\t\t\t<!--NOTE: Using \"include\" with no rules means nothing in this section will be logged-->\n\t\t</ImageLoad>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 8 : REMOTE THREAD CREATED [CreateRemoteThread]-->\n\t\t<!--COMMENT:\tMonitor for processes injecting code into other processes. Often used by malware to cloak their actions. Also when Firefox loads Flash.\n\t\t[ https://attack.mitre.org/wiki/Technique/T1055 ] -->\n\n\t\t<!--DATA: UtcTime, SourceProcessGuid, SourceProcessId, SourceImage, TargetProcessId, TargetImage, NewThreadId, StartAddress, StartModule, StartFunction-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<CreateRemoteThread onmatch=\"exclude\">\n\t\t\t<!--COMMENT: Exclude mostly-safe sources and log anything else.-->\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\wbem\\WmiPrvSE.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\svchost.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\wininit.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\csrss.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\services.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\winlogon.exe</SourceImage>\n\t\t\t<SourceImage condition=\"is\">C:\\Windows\\system32\\audiodg.exe</SourceImage>\n\t\t\t<StartModule condition=\"is\">C:\\Windows\\system32\\kernel32.dll</StartModule>\n\t\t\t<TargetImage condition=\"is\">C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe</TargetImage>\n\t\t</CreateRemoteThread>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 9 : RAW DISK ACCESS [RawAccessRead]-->\n\t\t<!--EVENT 9: \"RawAccessRead detected\"-->\n\t\t<!--COMMENT:\tCan cause high system load, disabled by default.-->\n\t\t<!--COMMENT:\tMonitor for raw sector-level access to the disk, often used to bypass access control lists or access locked files.\n\t\t\tDisabled by default since including even one entry here activates this component. Reward/performance/rule maintenance decision.\n\t\t\tEncourage you to experiment with this feature yourself. [ https://attack.mitre.org/wiki/Technique/T1067 ] -->\n\t\t<!--COMMENT:\tYou will likely want to set this to a full capture on domain controllers, where no process should be doing raw reads.-->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, Device-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<RawAccessRead onmatch=\"include\">\n\t\t\t<!--NOTE: Using \"include\" with no rules means nothing in this section will be logged-->\n\t\t</RawAccessRead>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 10 : INTER-PROCESS ACCESS [ProcessAccess]-->\n\t\t<!--EVENT 10: \"Process accessed\"-->\n\t\t<!--COMMENT:\tCan cause high system load, disabled by default.-->\n\t\t<!--COMMENT:\tMonitor for processes accessing other process' memory.-->\n\n\t\t<!--DATA: UtcTime, SourceProcessGuid, SourceProcessId, SourceThreadId, SourceImage, TargetProcessGuid, TargetProcessId, TargetImage, GrantedAccess, CallTrace-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ProcessAccess onmatch=\"include\">\n\t\t\t<!--NOTE: Using \"include\" with no rules means nothing in this section will be logged-->\n\t\t</ProcessAccess>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 11 : FILE CREATED [FileCreate]-->\n\t\t<!--EVENT 11: \"File created\"-->\n\t\t<!--NOTE:\tOther filesystem \"minifilters\" can make it appear to Sysmon that some files are being written twice. This is not a Sysmon issue, per Mark Russinovich.-->\n\t\t<!--NOTE:\tYou may not see files detected by antivirus. Other filesystem minifilters, like antivirus, can act before Sysmon receives the alert a file was written.-->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, TargetFilename, CreationUtcTime-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<FileCreate onmatch=\"include\">\n\t\t\t<TargetFilename name=\"T1023\" condition=\"contains\">\\Start Menu</TargetFilename> <!--Windows: Startup links and shortcut modification [ https://attack.mitre.org/wiki/Technique/T1023 ] -->\n\t\t\t<TargetFilename name=\"T1165\" condition=\"contains\">\\Startup\\</TargetFilename> <!--Microsoft:Changes to user's auto-launched files and shortcuts-->\n\t\t\t<TargetFilename name=\"OutlookAttachment\" condition=\"contains\">\\Content.Outlook\\</TargetFilename> <!--Microsoft:Outlook: attachments-->\n\t\t\t<TargetFilename name=\"Downloads\" condition=\"contains\">\\Downloads\\</TargetFilename> <!--Downloaded files. Does not include \"Run\" files in IE-->\n\t\t\t<TargetFilename condition=\"end with\">.application</TargetFilename> <!--Microsoft:ClickOnce: [ https://blog.netspi.com/all-you-need-is-one-a-clickonce-love-story/ ] -->\n\t\t\t<TargetFilename condition=\"end with\">.appref-ms</TargetFilename> <!--Microsoft:ClickOnce application | Credit @ion-storm -->\n\t\t\t<TargetFilename condition=\"end with\">.bat</TargetFilename> <!--Batch scripting-->\n\t\t\t<TargetFilename condition=\"end with\">.chm</TargetFilename>\n\t\t\t<TargetFilename condition=\"end with\">.cmd</TargetFilename> <!--Batch scripting: Batch scripts can also use the .cmd extension | Credit: @mmazanec -->\n\t\t\t<TargetFilename condition=\"end with\">.cmdline</TargetFilename> <!--Microsoft:dotNet: Executed by cvtres.exe-->\n\t\t\t<TargetFilename name=\"T1176\" condition=\"end with\">.crx</TargetFilename> <!--Chrome extension-->\n\t\t\t<TargetFilename condition=\"end with\">.dmp</TargetFilename> <!--Process dumps [ (fr) http://blog.gentilkiwi.com/securite/mimikatz/minidump ] -->\n\t\t\t<TargetFilename condition=\"end with\">.docm</TargetFilename> <!--Microsoft:Office:Word: Macro-->\n\t\t\t<TargetFilename name=\"DLL\" condition=\"end with\">.dll</TargetFilename> <!--Microsoft:Office:Word: Macro-->\n\t\t\t<TargetFilename name=\"EXE\" condition=\"end with\">.exe</TargetFilename> <!--Executable-->\n\t\t\t<TargetFilename name=\"ProcessHostingdotNETCode\" condition=\"end with\">.exe.log</TargetFilename> <!-- [ https://github.com/bitsadmin/nopowershell ] | Credit: @SBousseaden [ https://twitter.com/SBousseaden/status/1137493597769687040 ]  -->\n\t\t\t<TargetFilename condition=\"end with\">.jar</TargetFilename> <!--Java applets-->\n\t\t\t<TargetFilename condition=\"end with\">.jnlp</TargetFilename> <!--Java applets-->\n\t\t\t<TargetFilename condition=\"end with\">.jse</TargetFilename> <!--Scripting [ Example: https://www.sophos.com/en-us/threat-center/threat-analyses/viruses-and-spyware/Mal~Phires-C/detailed-analysis.aspx ] -->\n\t\t\t<TargetFilename condition=\"end with\">.hta</TargetFilename> <!--Scripting-->\n\t\t\t<TargetFilename condition=\"end with\">.job</TargetFilename> <!--Scheduled task-->\n\t\t\t<TargetFilename condition=\"end with\">.pptm</TargetFilename> <!--Microsoft:Office:Word: Macro-->\n\t\t\t<TargetFilename condition=\"end with\">.ps1</TargetFilename> <!--PowerShell [ More information: http://www.hexacorn.com/blog/2014/08/27/beyond-good-ol-run-key-part-16/ ] -->\n\t\t\t<TargetFilename condition=\"end with\">.sys</TargetFilename> <!--System driver files-->\n\t\t\t<TargetFilename condition=\"end with\">.scr</TargetFilename> <!--System driver files-->\n\t\t\t<TargetFilename condition=\"end with\">.vbe</TargetFilename> <!--VisualBasicScripting-->\n\t\t\t<TargetFilename condition=\"end with\">.vbs</TargetFilename> <!--VisualBasicScripting-->\n\t\t\t<TargetFilename condition=\"end with\">.xlsm</TargetFilename> <!--Microsoft:Office:Word: Macro-->\n\t\t\t<TargetFilename condition=\"end with\">.ocx</TargetFilename> <!--Microsoft:ActiveX-->\n\t\t\t<TargetFilename condition=\"end with\">proj</TargetFilename><!--Microsoft:MSBuild:Script: [ https://twitter.com/subTee/status/885919612969394177 ] -->\n\t\t\t<TargetFilename condition=\"end with\">.sln</TargetFilename><!--Microsoft:MSBuild:Script: [ https://twitter.com/subTee/status/885919612969394177 ] -->\n\t\t\t<TargetFilename condition=\"end with\">.xls</TargetFilename><!--Microsoft [ https://medium.com/@threathuntingteam/msxsl-exe-and-wmic-exe-a-way-to-proxy-code-execution-8d524f642b75 ] -->\n\t\t\t<TargetFilename name=\"DefaultUserModified\" condition=\"begin with\">C:\\Users\\Default</TargetFilename> <!--Windows: Changes to default user profile-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\system32\\Drivers</TargetFilename> <!--Microsoft: Drivers dropped here-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\SysWOW64\\Drivers</TargetFilename> <!--Microsoft: Drivers dropped here-->\n\t\t\t<TargetFilename name=\"T1037,T1484\" condition=\"begin with\">C:\\Windows\\system32\\GroupPolicy\\Machine\\Scripts</TargetFilename> <!--Group policy [ More information: http://www.hexacorn.com/blog/2017/01/07/beyond-good-ol-run-key-part-52/ ] -->\n\t\t\t<TargetFilename name=\"T1037,T1484\" condition=\"begin with\">C:\\Windows\\system32\\GroupPolicy\\User\\Scripts</TargetFilename> <!--Group policy [ More information: http://www.hexacorn.com/blog/2017/01/07/beyond-good-ol-run-key-part-52/ ] -->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\system32\\Wbem</TargetFilename> <!--Microsoft:WMI: [ More information: http://2014.hackitoergosum.org/slides/day1_WMI_Shell_Andrei_Dumitrescu.pdf ] -->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\SysWOW64\\Wbem</TargetFilename> <!--Microsoft:WMI: [ More information: http://2014.hackitoergosum.org/slides/day1_WMI_Shell_Andrei_Dumitrescu.pdf ] -->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\system32\\WindowsPowerShell</TargetFilename> <!--Microsoft:Powershell: Look for modifications for persistence [ https://www.malwarearchaeology.com/cheat-sheets ] -->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\SysWOW64\\WindowsPowerShell</TargetFilename> <!--Microsoft:Powershell: Look for modifications for persistence [ https://www.malwarearchaeology.com/cheat-sheets ] -->\n\t\t\t<TargetFilename name=\"T1053\" condition=\"begin with\">C:\\Windows\\Tasks\\</TargetFilename> <!--Microsoft:ScheduledTasks [ https://attack.mitre.org/wiki/Technique/T1053 ] -->\n\t\t\t<TargetFilename name=\"T1053\" condition=\"begin with\">C:\\Windows\\system32\\Tasks</TargetFilename> <!--Microsoft:ScheduledTasks [ https://attack.mitre.org/wiki/Technique/T1053 ] -->\n\t\t\t<TargetFilename name=\"T1053\" condition=\"begin with\">C:\\Windows\\SysWOW64\\Tasks</TargetFilename> <!--Microsoft:ScheduledTasks [ https://attack.mitre.org/wiki/Technique/T1053 ] -->\n\t\t\t<Image condition=\"begin with\">\\Device\\HarddiskVolumeShadowCopy</Image> <!--Nothing should be executing from VSC | Credit: @SBousseaden [ https://twitter.com/SBousseaden/status/1133030955407630336 ] -->\n\t\t\t<!--Windows application compatibility-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\AppPatch\\Custom</TargetFilename> <!--Windows: Application compatibility shims [ https://www.fireeye.com/blog/threat-research/2017/05/fin7-shim-databases-persistence.html ] -->\n\t\t\t<TargetFilename condition=\"contains\">VirtualStore</TargetFilename> <!--Windows: UAC virtualization [ https://blogs.msdn.microsoft.com/oldnewthing/20150902-00/?p=91681 ] -->\n\t\t\t<!--Exploitable file names-->\n\t\t\t<TargetFilename condition=\"end with\">.xls</TargetFilename> <!--Legacy Office files are often used for attacks-->\n\t\t\t<TargetFilename condition=\"end with\">.ppt</TargetFilename> <!--Legacy Office files are often used for attacks-->\n\t\t\t<TargetFilename condition=\"end with\">.rtf</TargetFilename> <!--RTF files often 0day malware vectors when opened by Office-->\n\t\t</FileCreate>\n\t</RuleGroup>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<FileCreate onmatch=\"exclude\">\n\t\t\t<!--SECTION: Microsoft-->\n\t\t\t<Image condition=\"is\">C:\\Program Files (x86)\\EMET 5.5\\EMET_Service.exe</Image> <!--Microsoft:EMET: Writes to C:\\Windows\\AppPatch\\-->\n\t\t\t<!--SECTION: Microsoft:Office:Click2Run-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\Common Files\\Microsoft Shared\\ClickToRun\\OfficeC2RClient.exe</Image> <!-- Microsoft:Office Click2Run-->\n\t\t\t<!--SECTION: Windows-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\smss.exe</Image> <!-- Windows: Session Manager SubSystem: Creates swapfile.sys,pagefile.sys,hiberfile.sys-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\CompatTelRunner.exe</Image> <!-- Windows: Windows 10 app, creates tons of cache files-->\n\t\t\t<Image condition=\"is\">\\\\?\\C:\\Windows\\system32\\wbem\\WMIADAP.EXE</Image> <!-- Windows: WMI Performance updates-->\n\t\t\t<Image condition=\"is\">C:\\Windows\\system32\\mobsync.exe</Image> <!--Windows: Network file syncing-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\system32\\DriverStore\\Temp\\</TargetFilename> <!-- Windows: Temp files by DrvInst.exe-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\system32\\wbem\\Performance\\</TargetFilename> <!-- Windows: Created in wbem by WMIADAP.exe-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\Windows\\Installer\\</TargetFilename> <!--Windows:Installer: Ignore MSI installer files caching-->\n\t\t\t<!--SECTION: Windows:Updates-->\n\t\t\t<TargetFilename condition=\"begin with\">C:\\$WINDOWS.~BT\\Sources\\</TargetFilename> <!-- Windows: Feature updates containing lots of .exe and .sys-->\n\t\t\t<Image condition=\"begin with\">C:\\Windows\\winsxs\\amd64_microsoft-windows</Image> <!-- Windows: Windows update-->\n\t\t</FileCreate>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 12 & 13 & 14 : REGISTRY MODIFICATION [RegistryEvent]-->\n\t\t<!--EVENT 12: \"Registry object added or deleted\"-->\n\t\t<!--EVENT 13: \"Registry value set\"-->\n\t\t<!--EVENT 14: \"Registry objected renamed\"-->\n\n\t\t<!--NOTE:\tWindows writes hundreds or thousands of registry keys a minute, so just because you're not changing things, doesn't mean these rules aren't being run.-->\n\t\t<!--NOTE:\tYou do not have to spend a lot of time worrying about performance, CPUs are fast, but it's something to consider. Every rule and condition type has a small cost.-->\n\t\t<!--NOTE:\t\"contains\" works by finding the first letter, then matching the second, etc, so the first letters should be as low-occurrence as possible.-->\n\t\t<!--NOTE:\t[ https://attack.mitre.org/wiki/Technique/T1112 ] -->\n\n\t\t<!--TECHNICAL:\tYou cannot filter on the \"Details\" attribute, due to performance issues when very large keys are written, and variety of data formats-->\n\t\t<!--TECHNICAL:\tPossible prefixes are HKLM, HKCR, and HKU-->\n\t\t<!--CRITICAL:\tSchema version 3.30 and higher change HKLM\\=\"\\REGISTRY\\MACHINE\\\" and HKU\\=\"\\REGISTRY\\USER\\\" and HKCR\\=\"\\REGISTRY\\MACHINE\\SOFTWARE\\Classes\\\" and CurrentControlSet=\"ControlSet001\"-->\n\t\t<!--CRITICAL:\tDue to a bug, Sysmon versions BEFORE 7.01 may not properly log with the new prefix style for registry keys that was originally introduced in schema version 3.30-->\n\t\t<!--NOTE:\tBecause Sysmon runs as a service, it has no filtering ability for, or concept of, HKCU or HKEY_CURRENT_USER. Use \"contains\" or \"end with\" to get around this limitation-->\n\n\t\t<!-- ! CRITICAL NOTE !:\tIt may appear this section is MISSING important entries, but SOME RULES MONITOR MANY KEYS, so look VERY CAREFULLY to see if something is already covered.\n\t\t\t\t\t\t\t\tSysmon's wildcard monitoring along with highly-tuned generic strings cuts the rulesets down immensely, compared to doing this in other tools.\n\t\t\t\t\t\t\t\tFor example, most COM hijacking in CLSID's across the registry is covered by a single rule monitoring a InProcServer32 wildcard-->\n\n\t\t<!--DATA: EventType, UtcTime, ProcessGuid, ProcessId, Image, TargetObject, Details (can't filter on), NewName (can't filter on)-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<RegistryEvent onmatch=\"include\">\n\t\t\t<!--Autorun or Startups-->\n\t\t\t\t<!--ADDITIONAL REFERENCE: [ http://www.ghacks.net/2016/06/04/windows-automatic-startup-locations/ ] -->\n\t\t\t\t<!--ADDITIONAL REFERENCE: [ https://view.officeapps.live.com/op/view.aspx?src=https://arsenalrecon.com/downloads/resources/Registry_Keys_Related_to_Autorun.ods ] -->\n\t\t\t\t<!--ADDITIONAL REFERENCE: [ http://www.silentrunners.org/launchpoints.html ] -->\n\t\t\t\t<!--ADDITIONAL REFERENCE: [ https://www.microsoftpressstore.com/articles/article.aspx?p=2762082&seqNum=2 ] -->\n\t\t\t\t<!--ADDITIONAL REFERENCE: [ https://web.archive.org/web/20200116001643/http://scholarworks.rit.edu/cgi/viewcontent.cgi?article=1533&context=theses | Understanding malware autostart techniques - Matthew Gottlieb ] -->\n\t\t\t<TargetObject name=\"T1060,RunKey\" condition=\"contains\">CurrentVersion\\Run</TargetObject> <!--Windows: Wildcard for Run keys, including RunOnce, RunOnceEx, RunServices, RunServicesOnce [Also covers terminal server] -->\n\t\t\t<TargetObject name=\"T1060,RunPolicy\" condition=\"contains\">Policies\\Explorer\\Run</TargetObject> <!--Windows: Alternate runs keys | Credit @ion-storm-->\n\t\t\t<TargetObject name=\"T1484\" condition=\"contains\">Group Policy\\Scripts</TargetObject> <!--Windows: Group policy scripts-->\n\t\t\t<TargetObject name=\"T1484\" condition=\"contains\">Windows\\System\\Scripts</TargetObject> <!--Windows: Wildcard for Logon, Loggoff, Shutdown-->\n\t\t\t<TargetObject name=\"T1060\" condition=\"contains\">CurrentVersion\\Windows\\Load</TargetObject> <!--Windows: [ https://msdn.microsoft.com/en-us/library/jj874148.aspx ] -->\n\t\t\t<TargetObject name=\"T1060\" condition=\"contains\">CurrentVersion\\Windows\\Run</TargetObject> <!--Windows: [ https://msdn.microsoft.com/en-us/library/jj874148.aspx ] -->\n\t\t\t<TargetObject name=\"T1060\" condition=\"contains\">CurrentVersion\\Winlogon\\Shell</TargetObject> <!--Windows: [ https://msdn.microsoft.com/en-us/library/ms838576(v=winembedded.5).aspx ] -->\n\t\t\t<TargetObject name=\"T1060\" condition=\"contains\">CurrentVersion\\Winlogon\\System</TargetObject> <!--Windows [ https://www.exterminate-it.com/malpedia/regvals/zlob-dns-changer/118 ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify</TargetObject> <!--Windows: Autorun location [ https://attack.mitre.org/wiki/Technique/T1004 ] [ https://www.cylance.com/windows-registry-persistence-part-2-the-run-keys-and-search-order ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Shell</TargetObject> <!--Windows: [ https://technet.microsoft.com/en-us/library/ee851671.aspx ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Userinit</TargetObject> <!--Windows: Autorun location [ https://www.cylance.com/windows-registry-persistence-part-2-the-run-keys-and-search-order ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\WOW6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32</TargetObject> <!--Windows: Legacy driver loading | Credit @ion-storm -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\BootExecute</TargetObject> <!--Windows: Autorun | Credit @ion-storm | [ https://www.cylance.com/windows-registry-persistence-part-2-the-run-keys-and-search-order ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug</TargetObject> <!--Windows: Automatic program crash debug program [ https://www.symantec.com/security_response/writeup.jsp?docid=2007-050712-5453-99&tabid=2 ] -->\n\t\t\t<TargetObject condition=\"contains\">UserInitMprLogonScript</TargetObject> <!--Windows: Legacy logon script environment variable [ http://www.hexacorn.com/blog/2014/11/14/beyond-good-ol-run-key-part-18/ ] -->\n\t\t\t<TargetObject name=\"T1112,ChangeStartupFolderPath\" condition=\"end with\">user shell folders\\startup</TargetObject> <!--Monitor changes to Startup folder location for monitoring evasion | Credit @SBousseaden-->\n\t\t\t<!--Services-->\n\t\t\t<TargetObject name=\"T1031,T1050\" condition=\"end with\">\\ServiceDll</TargetObject> <!--Windows: Points to a service's DLL [ https://blog.cylance.com/windows-registry-persistence-part-1-introduction-attack-phases-and-windows-services ] -->\n\t\t\t<TargetObject name=\"T1031,T1050\" condition=\"end with\">\\ServiceManifest</TargetObject> <!--Windows: Manifest pointing to service's DLL [ https://www.geoffchappell.com/studies/windows/win32/services/svchost/index.htm ] -->\n\t\t\t<TargetObject name=\"T1031,T1050\" condition=\"end with\">\\ImagePath</TargetObject> <!--Windows: Points to a service's EXE [ https://attack.mitre.org/wiki/Technique/T1050 ] -->\n\t\t\t<TargetObject name=\"T1031,T1050\" condition=\"end with\">\\Start</TargetObject> <!--Windows: Services start mode changes (Disabled, Automatically, Manual)-->\n\t\t\t<!--RDP-->\n\t\t\t<TargetObject name=\"RDP port change\" condition=\"end with\">Control\\Terminal Server\\WinStations\\RDP-Tcp\\PortNumber</TargetObject> <!--Windows: RDP port change under Control [ https://blog.menasec.net/2019/02/of-rdp-hijacking-part1-remote-desktop.html ]-->\n\t\t\t<TargetObject name=\"RDP port change\" condition=\"end with\">Control\\Terminal Server\\fSingleSessionPerUser</TargetObject> <!--Windows: Allow same user to have mutliple RDP sessions, to hide from admin being impersonated-->\n\t\t\t<TargetObject name=\"ModifyRemoteDesktopState\" condition=\"end with\">fDenyTSConnections</TargetObject> <!--Windows: Attacker turning on RDP-->\n\t\t\t<TargetObject condition=\"end with\">LastLoggedOnUser</TargetObject> <!--Windows: Changing last-logged in user-->\n\t\t\t<TargetObject name=\"ModifyRemoteDesktopPort\" condition=\"end with\">RDP-tcp\\PortNumber</TargetObject> <!--Windows: Changing RDP port to evade IDS-->\n\t\t\t<TargetObject condition=\"end with\">Services\\PortProxy\\v4tov4</TargetObject> <!--Windows: Changing RDP port to evade IDS-->\n\t\t\t<!--CLSID launch commands and Default File Association changes-->\n\t\t\t<TargetObject name=\"T1042\" condition=\"contains\">\\command\\</TargetObject> <!--Windows: Sensitive sub-key under file associations and CLSID that map to launch command-->\n\t\t\t<TargetObject name=\"T1122\" condition=\"contains\">\\ddeexec\\</TargetObject> <!--Windows: Sensitive sub-key under file associations and CLSID that map to launch command-->\n\t\t\t<TargetObject name=\"T1122\" condition=\"contains\">{86C86720-42A0-1069-A2E8-08002B30309D}</TargetObject> <!--Windows: Tooltip handler-->\n\t\t\t<TargetObject name=\"T1042\" condition=\"contains\">exefile</TargetObject> <!--Windows Executable handler, to log any changes not already monitored-->\n\t\t\t<!--Windows COM-->\n\t\t\t<TargetObject name=\"T1122\" condition=\"end with\">\\InprocServer32\\(Default)</TargetObject> <!--Windows:COM Object Hijacking [ https://blog.gdatasoftware.com/2014/10/23941-com-object-hijacking-the-discreet-way-of-persistence ] | Credit @ion-storm -->\n\t\t\t<!--Windows shell visual modifications used by malware-->\n\t\t\t<TargetObject name=\"T1158\" condition=\"end with\">\\Hidden</TargetObject> <!--Windows:Explorer: Some types of malware try to hide their hidden system files from the user, good signal event -->\n\t\t\t<TargetObject name=\"T1158\" condition=\"end with\">\\ShowSuperHidden</TargetObject> <!--Windows:Explorer: Some types of malware try to hide their hidden system files from the user, good signal event [ Example: https://www.symantec.com/security_response/writeup.jsp?docid=2007-061811-4341-99&tabid=2 ] -->\n\t\t\t<TargetObject name=\"T1158\" condition=\"end with\">\\HideFileExt</TargetObject> <!--Windows:Explorer: Some malware hides file extensions to make diagnosis/disinfection more daunting to novice users -->\n\t\t\t<!--Windows shell hijack and modifications-->\n\t\t\t<TargetObject condition=\"contains\">Classes\\*\\</TargetObject> <!--Windows:Explorer: [ http://www.silentrunners.org/launchpoints.html ] -->\n\t\t\t<TargetObject condition=\"contains\">Classes\\AllFilesystemObjects\\</TargetObject> <!--Windows:Explorer: [ http://www.silentrunners.org/launchpoints.html ] -->\n\t\t\t<TargetObject condition=\"contains\">Classes\\Directory\\</TargetObject> <!--Windows:Explorer: [ https://stackoverflow.com/questions/1323663/windows-shell-context-menu-option ] -->\n\t\t\t<TargetObject condition=\"contains\">Classes\\Drive\\</TargetObject> <!--Windows:Explorer: [ https://stackoverflow.com/questions/1323663/windows-shell-context-menu-option ] -->\n\t\t\t<TargetObject condition=\"contains\">Classes\\Folder\\</TargetObject> <!--Windows:Explorer: ContextMenuHandlers, DragDropHandlers, CopyHookHandlers, [ https://stackoverflow.com/questions/1323663/windows-shell-context-menu-option ] -->\n\t\t\t<TargetObject condition=\"contains\">Classes\\PROTOCOLS\\</TargetObject> <!--Windows:Explorer: Protocol handlers-->\n\t\t\t<TargetObject condition=\"contains\">ContextMenuHandlers\\</TargetObject> <!--Windows: [ http://oalabs.openanalysis.net/2015/06/04/malware-persistence-hkey_current_user-shell-extension-handlers/ ] -->\n\t\t\t<TargetObject condition=\"contains\">CurrentVersion\\Shell</TargetObject> <!--Windows: Shell Folders, ShellExecuteHooks, ShellIconOverloadIdentifers, ShellServiceObjects, ShellServiceObjectDelayLoad [ http://oalabs.openanalysis.net/2015/06/04/malware-persistence-hkey_current_user-shell-extension-handlers/ ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\explorer\\ShellExecuteHooks</TargetObject> <!--Windows: ShellExecuteHooks-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\explorer\\ShellServiceObjectDelayLoad</TargetObject> <!--Windows: ShellExecuteHooks-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\explorer\\ShellIconOverlayIdentifiers</TargetObject> <!--Windows: ShellExecuteHooks-->\n\t\t\t<!--AppPaths hijacking-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\</TargetObject> <!--Windows: Credit to @Hexacorn [ http://www.hexacorn.com/blog/2013/01/19/beyond-good-ol-run-key-part-3/ ] -->\n\t\t\t<!--Terminal service boobytrap-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp\\InitialProgram</TargetObject> <!--Windows:RDP: Note other Terminal Server run keys are handled by another wildcard already-->\n\t\t\t<!--Group Policy integrity-->\n\t\t\t<TargetObject name=\"T1484\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPExtensions\\</TargetObject> <!--Windows: Group Policy internally uses a plug-in architecture that nothing should be modifying-->\n\t\t\t<!--Winsock and Winsock2-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Services\\WinSock</TargetObject> <!--Windows: Wildcard, includes Winsock and Winsock2-->\n\t\t\t<TargetObject condition=\"end with\">\\ProxyServer</TargetObject> <!--Windows: System and user proxy server-->\n\t\t\t<!--Credential providers-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Authentication\\Credential Provider</TargetObject> <!--Wildcard, includes Credential Providers and Credential Provider Filters-->\n\t\t\t<TargetObject name=\"T1101\" condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\</TargetObject> <!-- [ https://attack.mitre.org/wiki/Technique/T1131 ] [ https://attack.mitre.org/wiki/Technique/T1101 ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SecurityProviders</TargetObject> <!--Windows: Changes to WDigest-UseLogonCredential for password scraping [ https://www.trustedsec.com/april-2015/dumping-wdigest-creds-with-meterpreter-mimikatzkiwi-in-windows-8-1/ ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Netsh</TargetObject> <!--Windows: Netsh helper DLL [ https://attack.mitre.org/wiki/Technique/T1128 ] -->\n\t\t\t<TargetObject condition=\"contains\">Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ProxyEnable</TargetObject> <!--Windows: Malware often disables a web proxy for 2nd stage downloads -->\n\t\t\t<!--Networking-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order\\</TargetObject> <!--Windows: Order of network providers that are checked to connect to destination [ https://www.malwarearchaeology.com/cheat-sheets ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\\Profiles</TargetObject> <!--Windows: | Credit @ion-storm -->\n\t\t\t<TargetObject name=\"T1089\" condition=\"end with\">\\EnableFirewall</TargetObject> <!--Windows: Monitor for firewall disablement, all firewall profiles [ https://attack.mitre.org/wiki/Technique/T1089 ] -->\n\t\t\t<TargetObject name=\"T1089\" condition=\"end with\">\\DoNotAllowExceptions</TargetObject> <!--Windows: Monitor for firewall disablement, all firewall profiles [ https://attack.mitre.org/wiki/Technique/T1089 ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\StandardProfile\\AuthorizedApplications\\List</TargetObject> <!--Windows Firewall authorized applications for all networks| Credit @ion-storm -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Services\\SharedAccess\\Parameters\\FirewallPolicy\\DomainProfile\\AuthorizedApplications\\List</TargetObject> <!--Windows Firewall authorized applications for domain networks -->\n\t\t\t<!--DLLs that get injected into every process at launch-->\n\t\t\t<TargetObject name=\"T1103\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows\\Appinit_Dlls\\</TargetObject> <!--Windows: Feature disabled by default [ https://attack.mitre.org/wiki/Technique/T1103 ] -->\n\t\t\t<TargetObject name=\"T1103\" condition=\"begin with\">HKLM\\Software\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows\\Appinit_Dlls\\</TargetObject> <!--Windows: Feature disabled by default [ https://attack.mitre.org/wiki/Technique/T1103 ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCertDlls\\</TargetObject> <!--Windows: Credit to @Hexacorn [ http://www.hexacorn.com/blog/2013/01/19/beyond-good-ol-run-key-part-3/ ] [ https://blog.comodo.com/malware/trojware-win32-trojanspy-volisk-a/ ] -->\n\t\t\t<!--Office-->\n\t\t\t<TargetObject name=\"T1137\" condition=\"contains\">Microsoft\\Office\\Outlook\\Addins\\</TargetObject> <!--Microsoft:Office: Outlook add-ins, access to sensitive data and often cause issues-->\n\t\t\t<TargetObject name=\"T1137\" condition=\"contains\">Office Test\\</TargetObject> <!-- Microsoft:Office: Persistence method [ http://www.hexacorn.com/blog/2014/04/16/beyond-good-ol-run-key-part-10/ ] | Credit @Hexacorn -->\n\t\t\t<TargetObject name=\"Context,ProtectedModeExitOrMacrosUsed\" condition=\"contains\">Security\\Trusted Documents\\TrustRecords</TargetObject> <!--Microsoft:Office: Monitor when \"Enable editing\" or \"Enable macros\" is used | Credit @OutflankNL | [ https://outflank.nl/blog/2018/01/16/hunting-for-evil-detect-macros-being-executed/ ] -->\n\t\t\t<TargetObject name=\"Context,ContactedDomain\" condition=\"end with\">\\EnableBHO</TargetObject> <!--Microsoft:Office: Contacted domains stored here 'HKEY_CURRENT_USER\\<SID>\\SOFTWARE\\Microsoft\\Office\\16.0\\Common\\Internet\\Server Cache\\<domain>\\EnableBHO' -->\n\t\t\t<!--IE-->\n\t\t\t<TargetObject name=\"T1176\" condition=\"contains\">Internet Explorer\\Toolbar\\</TargetObject> <!--Microsoft:InternetExplorer: Machine and user [ Example: https://www.exterminate-it.com/malpedia/remove-mywebsearch ] -->\n\t\t\t<TargetObject name=\"T1176\" condition=\"contains\">Internet Explorer\\Extensions\\</TargetObject> <!--Microsoft:InternetExplorer: Machine and user [ Example: https://www.exterminate-it.com/malpedia/remove-mywebsearch ] -->\n\t\t\t<TargetObject name=\"T1176\" condition=\"contains\">Browser Helper Objects\\</TargetObject> <!--Microsoft:InternetExplorer: Machine and user [ https://msdn.microsoft.com/en-us/library/bb250436(v=vs.85).aspx ] -->\n\t\t\t<TargetObject condition=\"end with\">\\DisableSecuritySettingsCheck</TargetObject>\n\t\t\t<TargetObject condition=\"end with\">\\3\\1206</TargetObject> <!--Microsoft:InternetExplorer: Malware sometimes assures scripting is on in Internet Zone [ https://support.microsoft.com/en-us/help/182569/internet-explorer-security-zones-registry-entries-for-advanced-users ] -->\n\t\t\t<TargetObject condition=\"end with\">\\3\\2500</TargetObject> <!--Microsoft:InternetExplorer: Malware sometimes disables Protected Mode in Internet Zone [ https://blog.avast.com/2013/08/12/your-documents-are-corrupted-from-image-to-an-information-stealing-trojan/ ] -->\n\t\t\t<TargetObject condition=\"end with\">\\3\\1809</TargetObject> <!--Microsoft:InternetExplorer: Malware sometimes disables Pop-up Blocker in Internet Zone [ https://support.microsoft.com/en-us/help/182569/internet-explorer-security-zones-registry-entries-for-advanced-users ] -->\n\t\t\t<!--Magic registry keys-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Classes\\CLSID\\{AB8902B4-09CA-4BB6-B78D-A8F59079A8D5}\\</TargetObject> <!--Windows: Thumbnail cache autostart [ http://blog.trendmicro.com/trendlabs-security-intelligence/poweliks-levels-up-with-new-autostart-mechanism/ ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Classes\\WOW6432Node\\CLSID\\{AB8902B4-09CA-4BB6-B78D-A8F59079A8D5}\\</TargetObject> <!--Windows: Thumbnail cache autostart [ http://blog.trendmicro.com/trendlabs-security-intelligence/poweliks-levels-up-with-new-autostart-mechanism/ ] -->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Classes\\CLSID\\{083863F1-70DE-11d0-BD40-00A0C911CE86}\\</TargetObject> <!--Windows: DirectX instances-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Classes\\WOW6432Node\\CLSID\\{083863F1-70DE-11d0-BD40-00A0C911CE86}\\</TargetObject> <!--Windows: DirectX instances-->\n\t\t\t<!--Install/Run artifacts-->\n\t\t\t<TargetObject condition=\"end with\">\\UrlUpdateInfo</TargetObject> <!--Microsoft:ClickOnce: Source URL is stored in this value [ https://subt0x10.blogspot.com/2016/12/mimikatz-delivery-via-clickonce-with.html ] -->\n\t\t\t<TargetObject condition=\"end with\">\\InstallSource</TargetObject> <!--Windows: Source folder for certain program and component installations-->\n\t\t\t<TargetObject name=\"Alert,Sysinternals Tool Used\" condition=\"end with\">\\EulaAccepted</TargetObject> <!--Sysinternals tool launched. Lots of useful abilities for attackers -->\n\t\t\t<!--Antivirus tampering-->\n\t\t\t<TargetObject name=\"T1089,Tamper-Defender\" condition=\"end with\">\\DisableAntiSpyware</TargetObject> <!--Windows:Defender: State modified via registry-->\n\t\t\t<TargetObject name=\"T1089,Tamper-Defender\" condition=\"end with\">\\DisableAntiVirus</TargetObject> <!--Windows:Defender: State modified via registry-->\n\t\t\t<TargetObject name=\"T1089,Tamper-Defender\" condition=\"end with\">\\SpynetReporting</TargetObject> <!--Windows:Defender: State modified via registry-->\n\t\t\t<TargetObject name=\"T1089,Tamper-Defender\" condition=\"end with\">DisableRealtimeMonitoring</TargetObject> <!--Windows:Defender: State modified via registry-->\n\t\t\t<TargetObject name=\"T1089,Tamper-Defender\" condition=\"end with\">\\SubmitSamplesConsent</TargetObject> <!--Windows:Defender: State modified via registry-->\n\t\t\t<!--Windows UAC tampering-->\n\t\t\t<TargetObject name=\"T1088\" condition=\"end with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\EnableLUA</TargetObject> <!--Detect: UAC Tampering | Credit @ion-storm -->\n\t\t\t<TargetObject name=\"T1088\" condition=\"end with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\LocalAccountTokenFilterPolicy</TargetObject> <!--Detect: UAC Tampering | Credit @ion-storm -->\n\t\t\t<!--Microsoft Security Center tampering | Credit @ion-storm -->\n\t\t\t<TargetObject name=\"T1089,Tamper-SecCenter\" condition=\"end with\">HKLM\\Software\\Microsoft\\Security Center\\</TargetObject> <!-- [ https://attack.mitre.org/wiki/Technique/T1089 ] -->\n\t\t\t<TargetObject name=\"T1089,Tamper-SecCenter\" condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\HideSCAHealth</TargetObject> <!--Windows:Security Center: Malware sometimes disables [ https://blog.avast.com/2013/08/12/your-documents-are-corrupted-from-image-to-an-information-stealing-trojan/ ] -->\n\t\t\t<!--Windows application compatibility-->\n\t\t\t<TargetObject name=\"T1138,AppCompatShim\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Custom</TargetObject> <!--Windows: AppCompat [ https://www.fireeye.com/blog/threat-research/2017/05/fin7-shim-databases-persistence.html ] -->\n\t\t\t<TargetObject name=\"T1138,AppCompatShim\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\InstalledSDB</TargetObject> <!--Windows: AppCompat [ https://attack.mitre.org/wiki/Technique/T1138 ] -->\n\t\t\t<TargetObject condition=\"contains\">VirtualStore</TargetObject> <!--Windows: Registry virtualization, something's wrong if it's in use [ https://msdn.microsoft.com/en-us/library/windows/desktop/aa965884(v=vs.85).aspx ] -->\n\t\t\t<!--Windows internals integrity monitoring-->\n\t\t\t<TargetObject name=\"T1183,IFEO\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\</TargetObject> <!--Windows: Malware likes changing IFEO, like adding Debugger to disable antivirus EXE-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\</TargetObject> <!--Windows: Event log system integrity and ACLs-->\n\t\t\t<TargetObject name=\"Tamper-Safemode\" condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Safeboot\\</TargetObject> <!--Windows: Services approved to load in safe mode. Almost nothing should ever modify this.-->\n\t\t\t<TargetObject name=\"Tamper-Winlogon\" condition=\"begin with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Winlogon\\</TargetObject> <!--Windows: Providers notified by WinLogon-->\n\t\t\t<TargetObject name=\"Context,DeviceConnectedOrUpdated\" condition=\"end with\">\\FriendlyName</TargetObject> <!--Windows: New devices connected and remembered-->\n\t\t\t<TargetObject name=\"Context,MsiInstallerStarted\" condition=\"is\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\InProgress\\(Default)</TargetObject> <!--Windows: See when WindowsInstaller is engaged, useful for timeline matching with other events-->\n\t\t\t<TargetObject name=\"Tamper-Tracing\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Tracing\\RASAPI32</TargetObject> <!--Windows: Malware sometimes disables tracing to obfuscate tracks-->\n\t\t\t<TargetObject name=\"Context,ProcessAccessedPrivateResource\" condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\CapabilityAccessManager\\ConsentStore\\</TargetObject> <!-- Windows: Win10 tracks when and what process uses webcam/microphone/location etc [ https://medium.com/@7a616368/can-you-track-processes-accessing-the-camera-and-microphone-7e6885b37072 ] -->\n\t\t\t<!--Windows inventory events-->\n\t\t\t<TargetObject name=\"InvDB-Path\" condition=\"end with\">\\LowerCaseLongPath</TargetObject> <!-- [ https://binaryforay.blogspot.com/2017/10/amcache-still-rules-everything-around.html ] -->\n\t\t\t<TargetObject name=\"InvDB-Pub\" condition=\"end with\">\\Publisher</TargetObject> <!-- [ https://binaryforay.blogspot.com/2017/10/amcache-still-rules-everything-around.html ] -->\n\t\t\t<TargetObject name=\"InvDB-Ver\" condition=\"end with\">\\BinProductVersion</TargetObject> <!-- [ https://docs.microsoft.com/en-us/windows/privacy/basic-level-windows-diagnostic-events-and-fields-1709 ] -->\n\t\t\t<TargetObject name=\"InvDB-DriverVer\" condition=\"end with\">\\DriverVersion</TargetObject> <!-- [ https://df-stream.com/2015/02/leveraging-devicecontainers-key/ ] -->\n\t\t\t<TargetObject name=\"InvDB-DriverVer\" condition=\"end with\">\\DriverVerVersion</TargetObject> <!-- [ https://df-stream.com/2015/02/leveraging-devicecontainers-key/ ] -->\n\t\t\t<TargetObject name=\"InvDB-CompileTimeClaim\" condition=\"end with\">\\LinkDate</TargetObject> <!-- Compile time of EXE, may not be reliable [ https://en.wikipedia.org/wiki/Link_time ] -->\n\t\t\t<TargetObject name=\"InvDB\" condition=\"contains\">Compatibility Assistant\\Store\\</TargetObject> <!-- Inventory -->\n\t\t\t<!--Suspicious sources-->\n\t\t\t<Image name=\"Suspicious,ImageBeginWithBackslash\" condition=\"end with\">regedit.exe</Image> <!--Users and helpdesk staff making system modifications -->\n\t\t\t<Image name=\"Suspicious,ImageBeginWithBackslash\" condition=\"begin with\">\\</Image> <!--Devices and VSC shouldn't be executing changes | Credit: @SBousseaden @ionstorm @neu5ron @PerchedSystems [ https://twitter.com/SwiftOnSecurity/status/1133167323991486464 ] -->\n\t\t</RegistryEvent>\n\t</RuleGroup>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<RegistryEvent onmatch=\"exclude\">\n\t\t<!--COMMENT:\tRemove low-information noise. Often these hide a procress recreating an empty key and do not hide the values created subsequently.-->\n\t\t<!--NOTE:\tA lot of noise can be removed by excluding CreateKey events, which are largely innocuous-->\n\t\t\t<TargetObject condition=\"contains\">\\{CAFEEFAC-</TargetObject>\n\t\t\t<EventType condition=\"is\">CreateKey</EventType>\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\COMPONENTS</TargetObject>\n\t\t\t<!--Inventory noise-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\AppModel\\StateRepository\\Cache</TargetObject>\n\t\t\t<!--Misc-->\n\t\t\t<TargetObject condition=\"end with\">Toolbar\\WebBrowser</TargetObject> <!--Microsoft:IE: Extraneous activity-->\n\t\t\t<TargetObject condition=\"end with\">Browser\\ITBar7Height</TargetObject> <!--Microsoft:IE: Extraneous activity, covers ShellBrowser and WebBrowser-->\n\t\t\t<TargetObject condition=\"end with\">Browser\\ITBar7Layout</TargetObject> <!--Microsoft:IE: Extraneous activity-->\n\t\t\t<TargetObject condition=\"end with\">Internet Explorer\\Toolbar\\Locked</TargetObject> <!--Windows:Explorer: Extraneous activity-->\n\t\t\t<TargetObject condition=\"end with\">Toolbar\\WebBrowser\\{47833539-D0C5-4125-9FA8-0819E2EAAC93}</TargetObject> <!--Windows:Explorer: Extraneous activity-->\n\t\t\t<TargetObject condition=\"end with\">}\\PreviousPolicyAreas</TargetObject> <!--Windows: Remove noise from \\Winlogon\\GPExtensions by svchost.exe-->\n\t\t\t<TargetObject condition=\"contains\">\\Control\\WMI\\Autologger\\</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">HKLM\\SYSTEM\\CurrentControlSet\\Services\\UsoSvc\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">\\Lsa\\OfflineJoin\\CurrentValue</TargetObject> <!--Windows: Sensitive value during domain join-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\</TargetObject> <!--Windows: Remove noise monitoring installations run as system-->\n\t\t\t<TargetObject condition=\"contains\">_Classes\\AppX</TargetObject> <!--Windows: Remove noise monitoring \"Shell\\open\\command\"--> <!--Win8+-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\</TargetObject> <!--Windows: SvcHost Noise-->\n\t\t\t<!--Bootup Control noise-->\n\t\t\t<TargetObject condition=\"end with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\LsaPid</TargetObject> <!--Windows:lsass.exe: Boot noise-->\n\t\t\t<TargetObject condition=\"end with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\SspiCache</TargetObject> <!--Windows:lsass.exe: Boot noise--> <!--Win8+-->\n\t\t\t<TargetObject condition=\"end with\">HKLM\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\Kerberos\\Domains</TargetObject> <!--Windows:lsass.exe: Boot noise--> <!--Win8+-->\n\t\t\t<!--Services startup settings noise, some low-risk services routinely change it and this can be ignored-->\n\t\t\t<TargetObject condition=\"end with\">\\Services\\BITS\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\clr_optimization_v2.0.50727_32\\Start</TargetObject> <!--Microsoft:dotNet: Windows 7-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\clr_optimization_v2.0.50727_64\\Start</TargetObject> <!--Microsoft:dotNet: Windows 7-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\clr_optimization_v4.0.30319_32\\Start</TargetObject> <!--Microsoft:dotNet: Windows 10-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\clr_optimization_v4.0.30319_64\\Start</TargetObject> <!--Microsoft:dotNet: Windows 10-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\deviceAssociationService\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\fhsvc\\Start</TargetObject> <!--Windows: File History Service-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\nal\\Start</TargetObject> <!--Intel: Network adapter diagnostic driver-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\trustedInstaller\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\tunnel\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<TargetObject condition=\"end with\">\\services\\usoSvc\\Start</TargetObject> <!--Windows: Remove noise from monitoring \"\\Start\"-->\n\t\t\t<!--FileExts noise filtering-->\n\t\t\t<TargetObject condition=\"end with\">\\UserChoice\\ProgId</TargetObject> <!--Windows: Remove noise from monitoring \"FileExts\"--> <!--Win8+-->\n\t\t\t<TargetObject condition=\"end with\">\\UserChoice\\Hash</TargetObject> <!--Windows: Remove noise from monitoring \"FileExts\"--> <!--Win8+-->\n\t\t\t<TargetObject condition=\"end with\">\\OpenWithList\\MRUList</TargetObject> <!--Windows: Remove noise from monitoring \"FileExts\"-->\n\t\t\t<TargetObject condition=\"contains\">Shell Extentions\\Cached</TargetObject> <!--Windows: Remove noise generated by explorer.exe on monitored ShellCached binary keys--> <!--Win8+-->\n\t\t\t<!--Group Policy noise-->\n\t\t\t<TargetObject condition=\"end with\">HKLM\\System\\CurrentControlSet\\Control\\Lsa\\Audit\\SpecialGroups</TargetObject> <!--Windows: Routinely set through Group Policy, not especially important to log-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Startup\\0\\PSScriptOrder</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Startup\\0\\SOM-ID</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Startup\\0\\GPO-ID</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Startup\\0\\0\\IsPowershell</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Startup\\0\\0\\ExecTime</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Shutdown\\0\\PSScriptOrder</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Shutdown\\0\\SOM-ID</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Shutdown\\0\\GPO-ID</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Shutdown\\0\\0\\IsPowershell</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"end with\">SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\Scripts\\Shutdown\\0\\0\\ExecTime</TargetObject> <!--Windows:Group Policy: Noise below the actual key while building-->\n\t\t\t<TargetObject condition=\"contains\">\\safer\\codeidentifiers\\0\\HASHES\\{</TargetObject> <!--Windows: Software Restriction Policies. Can be used to disable security tools, but very noisy to monitor if you use it-->\n\t\t\t<!--SECTION: Office C2R-->\n\t\t\t<TargetObject condition=\"contains\">VirtualStore\\MACHINE\\SOFTWARE\\Microsoft\\Office\\ClickToRun\\</TargetObject> <!--Microsoft: SearchProtocolHost writes to OfficeC2R registry for Outlook, seemingly regarding mail indexing-->\n\t\t\t<TargetObject condition=\"begin with\">HKLM\\SOFTWARE\\Microsoft\\Office\\ClickToRun\\</TargetObject> <!--Microsoft: Virtual registry for Office-->\n\t\t\t<!--SECTION: 3rd party-->\n\t\t\t<Image condition=\"is\">C:\\Program Files\\WIDCOMM\\Bluetooth Software\\btwdins.exe</Image> <!--Constantly writes to HKLM-->\n\t\t\t<TargetObject condition=\"begin with\">HKCR\\VLC.</TargetObject> <!--VLC update noise-->\n\t\t\t<TargetObject condition=\"begin with\">HKCR\\iTunes.</TargetObject> <!--Apple: iTunes update noise-->\n\t\t\t<!--WINEVT publishers noise-->\n\t\t\t<TargetObject condition=\"is\">HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\WINEVT\\Publishers\\{945a8954-c147-4acd-923f-40c45405a658}</TargetObject> <!--Windows update-->\n\t\t</RegistryEvent>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 15 : ALTERNATE DATA STREAM CREATED [FileCreateStreamHash]-->\n\t\t<!--EVENT 15: \"File stream created\"-->\n\t\t<!--COMMENT:\tAny files created with an NTFS Alternate Data Stream which match these rules will be hashed and logged.\n\t\t\t[ https://blogs.technet.microsoft.com/askcore/2013/03/24/alternate-data-streams-in-ntfs/ ]\n\t\t\tADS's are used by browsers and email clients to mark files as originating from the Internet or other foreign sources.\n\t\t\t[ https://textslashplain.com/2016/04/04/downloads-and-the-mark-of-the-web/ ] -->\n\t\t<!--NOTE: Other filesystem minifilters can make it appear to Sysmon that some files are being written twice. This is not a Sysmon issue, per Mark Russinovich.-->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, Image, TargetFilename, CreationUtcTime, Hash-->\n\t\t<FileCreateStreamHash onmatch=\"include\">\n\t\t\t<TargetFilename condition=\"contains\">Downloads</TargetFilename> <!--Downloaded files. Does not include \"Run\" files in IE-->\n\t\t\t<TargetFilename condition=\"contains\">Temp\\7z</TargetFilename> <!--7zip extractions-->\n\t\t\t<TargetFilename condition=\"contains\">Startup</TargetFilename> <!--ADS startup | Example: [ https://www.hybrid-analysis.com/sample/a314f6106633fba4b70f9d6ddbee452e8f8f44a72117749c21243dc93c7ed3ac?environmentId=100 ] -->\n\t\t\t<TargetFilename condition=\"end with\">.bat</TargetFilename> <!--Batch scripting-->\n\t\t\t<TargetFilename condition=\"end with\">.cmd</TargetFilename> <!--Batch scripting | Credit @ion-storm -->\n\t\t\t<TargetFilename condition=\"end with\">.doc</TargetFilename> <!--Office doc potentially with macro -->\n\t\t\t<TargetFilename condition=\"end with\">.hta</TargetFilename> <!--Scripting-->\n\t\t\t<TargetFilename condition=\"end with\">.lnk</TargetFilename> <!--Shortcut file | Credit @ion-storm -->\n\t\t\t<TargetFilename condition=\"end with\">.ppt</TargetFilename> <!--Office doc potentially with macros-->\n\t\t\t<TargetFilename condition=\"end with\">.ps1</TargetFilename> <!--PowerShell-->\n\t\t\t<TargetFilename condition=\"end with\">.ps2</TargetFilename> <!--PowerShell-->\n\t\t\t<TargetFilename condition=\"end with\">.reg</TargetFilename> <!--Registry File-->\n\t\t\t<TargetFilename condition=\"end with\">.jse</TargetFilename> <!--Registry File-->\n\t\t\t<TargetFilename condition=\"end with\">.vb</TargetFilename> <!--VisualBasicScripting files-->\n\t\t\t<TargetFilename condition=\"end with\">.vbe</TargetFilename> <!--VisualBasicScripting files-->\n\t\t\t<TargetFilename condition=\"end with\">.vbs</TargetFilename> <!--VisualBasicScripting files-->\n\t\t</FileCreateStreamHash>\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<FileCreateStreamHash onmatch=\"exclude\">\n\t\t</FileCreateStreamHash>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 16 : SYSMON CONFIGURATION CHANGE-->\n\t\t<!--EVENT 16: \"Sysmon config state changed\"-->\n\t\t<!--COMMENT:\tThis ONLY logs if the hash of the configuration changes. Running \"sysmon.exe -c\" with the current configuration will not be logged with Event 16-->\n\t\t\n\t\t<!--DATA: UtcTime, Configuration, ConfigurationFileHash-->\n\t\t<!--Cannot be filtered.-->\n\n\t<!--SYSMON EVENT ID 17 & 18 : PIPE CREATED / PIPE CONNECTED [PipeEvent]-->\n\t\t<!--EVENT 17: \"Pipe Created\"-->\n\t\t<!--EVENT 18: \"Pipe Connected\"-->\n\n\t\t<!--ADDITIONAL REFERENCE: [ https://www.cobaltstrike.com/help-smb-beacon ] -->\n\t\t<!--ADDITIONAL REFERENCE: [ https://blog.cobaltstrike.com/2015/10/07/named-pipe-pivoting/ ] -->\n\n\t\t<!--DATA: UtcTime, ProcessGuid, ProcessId, PipeName, Image-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<PipeEvent onmatch=\"include\">\n\t\t\t<!--NOTE: Using incide with no rules means nothing in this section will be logged-->\n\t\t</PipeEvent>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 19 & 20 & 21 : WMI EVENT MONITORING [WmiEvent]-->\n\t\t<!--EVENT 19: \"WmiEventFilter activity detected\"-->\n\t\t<!--EVENT 20: \"WmiEventConsumer activity detected\"-->\n\t\t<!--EVENT 21: \"WmiEventConsumerToFilter activity detected\"-->\n\n\t\t<!--ADDITIONAL REFERENCE: [ https://www.darkoperator.com/blog/2017/10/15/sysinternals-sysmon-610-tracking-of-permanent-wmi-events ] -->\n\t\t<!--ADDITIONAL REFERENCE: [ https://rawsec.lu/blog/posts/2017/Sep/19/sysmon-v610-vs-wmi-persistence/ ] -->\n\n\t\t<!--DATA: EventType, UtcTime, Operation, User, Name, Type, Destination, Consumer, Filter-->\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<WmiEvent onmatch=\"exclude\">\n\t\t\t<!--NOTE: Using exclude with no rules means everything will be logged-->\n\t\t</WmiEvent>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 22 : DNS QUERY [DnsQuery]-->\n\t\t<!--EVENT 22: \"Dns query\"-->\n\n\t\t<!--NOTE:\tDue to the volume of events that DNS queries generate, some orgs may want to remove this section from their configuration to reduce Sysmon log turnover. -->\n\n\t\t<!--COMMENT:\tDNS logging is a very nuanced challenge in monitoring due to event volume. Legitimate domains can be used to host malware/C2, but lookup itself is not very informative.\n\t\t\t\t\t\tIt's fine to exclude monitoring these bulk low-value lookups, but at same time, you would not have a full log of how malware communicated, potentially missing C2.\n\t\t\t\t\t\tThis section of Sysmon configuration will require your full judgement and knowledge of your org's priorities. There is no correct answer.-->\n\n\t\t<!--OPERATIONS:\tChrome and Firefox prefetch DNS lookups, or use alternate DNS lookup methods Sysmon won't capture. You need to turn these off.\n\t\t\t\t\t\tSearch for Group Policy for these browsers to configure this.-->\n\n\t\t<!--OPERATIONS:\tMost DNS traffic is web advertising. To significantly reduce DNS queries and malware ads, enable client-side advertising filtering via Group Policy. This is easy.\n\t\t\t\tInternet Explorer: https://decentsecurity.com/adblocking-for-internet-explorer-deployment/\n\t\t\t\tChrome: https://decentsecurity.com/ublock-for-google-chrome-deployment/\n\t\t\t\tFirefox: ToDo\n\t\t\t\t\t\tAlso note, this configuration is designed for United States computers. Your country's users will may need customization to reduce noise.\n\t\t\t-->\n\n\t\t<!--CONFIG:\tDNS poisoning is an issue during threat investigations. Try to only exclude ROUTINE system-level queries you know are strongly validated with HTTPS or code signing.-->\n\t\t<!--CONFIG:\tIf you exclude microsoft.com, someone could register malware-microsoft.com and it wouldn't be logged. Use \"END WITH\" with leading . or \"IS\" operators.-->\n\t\t<!--CONFIG:\tBe very specific in exclusions. Threat actors use legitimate services, too. Dont exclude all of AWS or Azure or Google or CDNs!-->\n\t\t<!--CONFIG: Popularity data: [ http://s3-us-west-1.amazonaws.com/umbrella-static/index.html ] [ https://better.fyi/trackers/alexa-top-500-news/ ] -->\n\n\t\t<!--CRITICAL:\tDo NOT exclude \"wpad\" lookups. This is a MitM vector routinely used by attackers. Disable WPAD or enforce client-side DNSSEC for AD domain lookups.-->\n\t\t<!--CRITICAL:\tDo NOT exclude IPv6 lookups.-->\n\n\t\t<!--DATA: RuleName, UtcTime, ProcessGuid, ProcessId, QueryName, QueryType, QueryStatus, QueryResults (can't filter on)-->\n\n\t\t<!--BELOW: These domains should not be excluded at the top level. Be specific if you want to reduce noise under them.-->\n\t\t<!-- Rejected: .cloudapp.net, customer content [ https://blogs.technet.microsoft.com/ptsblog/2012/06/18/security-consideration-when-using-cloudapp-net-domain-as-production-environment-in-windows-azure/ ] -->\n\t\t<!-- Rejected: .googleapis.com, customer content [ https://www.zdnet.com/article/this-business-email-scam-spreads-trojans-through-google-cloud-storage/ ] -->\n\t\t<!-- Rejected: .cloudfront.net, customer content -->\n\t\t<!-- Rejected: .windows.net, customer content -->\n\t\t<!-- Rejected: *github.com, customer content, including open-source malware components -->\n\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<DnsQuery onmatch=\"exclude\">\n\t\t\t<!--Network noise-->\n\t\t\t<QueryName condition=\"end with\">.arpa.</QueryName> <!--Design decision to not log reverse DNS lookups. You will need to decide.-->\n\t\t\t<QueryName condition=\"end with\">.arpa</QueryName> <!--Design decision to not log reverse DNS lookups. You will need to decide.-->\n\t\t\t<QueryName condition=\"end with\">.msftncsi.com</QueryName> <!--Microsoft proxy detection | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"is\">..localmachine</QueryName>\n\t\t\t<QueryName condition=\"is\">localhost</QueryName>\n\t\t\t<!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">-pushp.svc.ms</QueryName> <!--Microsoft: Doesn't appear to host customer content or subdomains-->\n\t\t\t<QueryName condition=\"end with\">.b-msedge.net</QueryName> <!--Microsoft: Doesn't appear to host customer content or subdomains-->\n\t\t\t<QueryName condition=\"end with\">.bing.com</QueryName> <!-- Microsoft | Microsoft default exclusion -->\n\t\t\t<QueryName condition=\"end with\">.hotmail.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.live.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.live.net</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.s-microsoft.com</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">.microsoft.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.microsoftonline.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.microsoftstore.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.ms-acdc.office.com</QueryName> <!--Microsoft: Doesn't appear to host customer content or subdomains-->\n\t\t\t<QueryName condition=\"end with\">.msedge.net</QueryName> <!--Microsoft: Doesn't appear to host customer content or subdomains-->\n\t\t\t<QueryName condition=\"end with\">.msn.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.msocdn.com</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">.skype.com</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.skype.net</QueryName> <!--Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.windows.com</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">.windows.net.nsatc.net</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">.windowsupdate.com</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"end with\">.xboxlive.com</QueryName> <!--Microsoft-->\n\t\t\t<QueryName condition=\"is\">login.windows.net</QueryName> <!--Microsoft-->\n\t\t\t<Image condition=\"begin with\">C:\\ProgramData\\Microsoft\\Windows Defender\\Platform\\</Image> <!--Microsoft: https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/network-protection -->\n\t\t\t<!--Microsoft:Office365/AzureAD-->\n\t\t\t<QueryName condition=\"end with\">.activedirectory.windowsazure.com</QueryName> <!--Microsoft: AzureAD-->\n\t\t\t<QueryName condition=\"end with\">.aria.microsoft.com</QueryName> <!--Microsoft: OneDrive/SharePoint-->\n\t\t\t<QueryName condition=\"end with\">.msauth.net</QueryName>\n\t\t\t<QueryName condition=\"end with\">.msftauth.net</QueryName>\n\t\t\t<QueryName condition=\"end with\">.office.net</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"end with\">.opinsights.azure.com</QueryName> <!--Microsoft: AzureAD/InTune client event monitoring-->\n\t\t\t<QueryName condition=\"end with\">.res.office365.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">acdc-direct.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">atm-fp-direct.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">loki.delve.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">management.azure.com</QueryName> <!--Microsoft: AzureAD/InTune-->\n\t\t\t<QueryName condition=\"is\">messaging.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">outlook.office365.com</QueryName> <!--Microsoft: Protected by HSTS-->\n\t\t\t<QueryName condition=\"is\">portal.azure.com</QueryName> <!--Microsoft: AzureAD/InTune-->\n\t\t\t<QueryName condition=\"is\">protection.outlook.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"is\">substrate.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<QueryName condition=\"end with\">.measure.office.com</QueryName> <!--Microsoft: Office-->\n\t\t\t<!--3rd-party applications-->\n\t\t\t<QueryName condition=\"end with\">.adobe.com</QueryName> <!--Adobe-->\n\t\t\t<QueryName condition=\"end with\">.adobe.io</QueryName> <!--Adobe-->\n\t\t\t<QueryName condition=\"end with\">.mozaws.net</QueryName> <!--Mozilla-->\n\t\t\t<QueryName condition=\"end with\">.mozilla.com</QueryName> <!--Mozilla-->\n\t\t\t<QueryName condition=\"end with\">.mozilla.net</QueryName> <!--Mozilla-->\n\t\t\t<QueryName condition=\"end with\">.mozilla.org</QueryName> <!--Mozilla-->\n\t\t\t<QueryName condition=\"end with\">.spotify.com</QueryName> <!--Spotify-->\n\t\t\t<QueryName condition=\"end with\">.spotify.map.fastly.net</QueryName> <!--Spotify-->\n\t\t\t<QueryName condition=\"end with\">.wbx2.com</QueryName> <!--Webex-->\n\t\t\t<QueryName condition=\"end with\">.webex.com</QueryName> <!--Webex-->\n\t\t\t<QueryName condition=\"is\">clients1.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clients2.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clients3.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clients4.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clients5.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clients6.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">safebrowsing.googleapis.com</QueryName> <!--Google-->\n\t\t\t<!--Goodlist CDN-->\n\t\t\t<QueryName condition=\"end with\">.akadns.net</QueryName> <!--AkamaiCDN, extensively used by Microsoft | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.netflix.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">aspnetcdn.com</QueryName> <!--Microsoft [ https://docs.microsoft.com/en-us/aspnet/ajax/cdn/overview ]-->\n\t\t\t<QueryName condition=\"is\">ajax.googleapis.com</QueryName>\n\t\t\t<QueryName condition=\"is\">cdnjs.cloudflare.com</QueryName> <!--Cloudflare: Hosts popular javascript libraries-->\n\t\t\t<QueryName condition=\"is\">fonts.googleapis.com</QueryName> <!--Google fonts-->\n\t\t\t<QueryName condition=\"end with\">.typekit.net</QueryName> <!--Adobe fonts-->\n\t\t\t<QueryName condition=\"is\">cdnjs.cloudflare.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.stackassets.com</QueryName> <!--Stack Overflow-->\n\t\t\t<QueryName condition=\"end with\">.steamcontent.com</QueryName>\n\t\t\t<QueryName condition=\"is\">play.google.com</QueryName>\n\t\t\t<QueryName condition=\"is\">content-autofill.googleapis.com</QueryName>\n\t\t\t<!--Web resources-->\n\t\t\t<QueryName condition=\"end with\">.disqus.com</QueryName> <!--Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.fontawesome.com</QueryName>\n\t\t\t<QueryName condition=\"is\">disqus.com</QueryName> <!--Microsoft default exclusion-->\n\t\t\t<!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.1rx.io</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.2mdn.net</QueryName> <!--Ads: Google | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.3lift.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adadvisor.net</QueryName> <!--Ads: Neustar [ https://better.fyi/trackers/adadvisor.net/ ] -->\n\t\t\t<QueryName condition=\"end with\">.adap.tv</QueryName> <!--Ads:AOL | Microsoft default exclusion [ https://www.crunchbase.com/organization/adap-tv ] -->\n\t\t\t<QueryName condition=\"end with\">.addthis.com</QueryName> <!--Ads:Oracle | Microsoft default exclusion [ https://en.wikipedia.org/wiki/AddThis ] -->\n\t\t\t<QueryName condition=\"end with\">.adform.net</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adnxs.com</QueryName> <!--Ads: AppNexus | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.adroll.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adrta.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adsafeprotected.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adsrvr.org</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.adsymptotic.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.advertising.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.agkn.com</QueryName> <!--Ads | [ https://www.home.neustar/privacy ] -->\n\t\t\t<QueryName condition=\"end with\">.amazon-adsystem.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.amazon-adsystem.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.analytics.yahoo.com</QueryName> <!--Ads:Yahoo-->\n\t\t\t<QueryName condition=\"end with\">.aol.com</QueryName> <!--Ads | Microsoft default exclusion -->\n\t\t\t<QueryName condition=\"end with\">.betrad.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.bidswitch.net</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.casalemedia.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.chartbeat.net</QueryName> <!--Ads | Microsoft default exclusion [ https://better.fyi/trackers/chartbeat.com/ ]-->\n\t\t\t<QueryName condition=\"end with\">.cnn.com</QueryName> <!-- Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.convertro.com</QueryName> <!--Ads:Verizon-->\n\t\t\t<QueryName condition=\"end with\">.criteo.com</QueryName> <!--Ads [ https://better.fyi/trackers/criteo.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.criteo.net</QueryName> <!--Ads [ https://better.fyi/trackers/criteo.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.crwdcntrl.net</QueryName> <!--Ads: Lotame [ https://better.fyi/trackers/crwdcntrl.net/ ] -->\n\t\t\t<QueryName condition=\"end with\">.demdex.net</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.domdex.com</QueryName> \n\t\t\t<QueryName condition=\"end with\">.dotomi.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.doubleclick.net</QueryName> <!--Ads:Conversant | Microsoft default exclusion [ https://www.crunchbase.com/organization/dotomi ] -->\n\t\t\t<QueryName condition=\"end with\">.doubleverify.com</QueryName> <!--Ads: Google-->\n\t\t\t<QueryName condition=\"end with\">.emxdgt.com</QueryName> <!--Ads: EMX-->\n\t\t\t<QueryName condition=\"end with\">.everesttech.net</QueryName> <!--Ads | [ https://better.fyi/trackers/everesttech.net/ ] -->\n\t\t\t<QueryName condition=\"end with\">.exelator.com</QueryName> <!--Ads:Nielson Marketing Cloud-->\n\t\t\t<QueryName condition=\"end with\">.google-analytics.com</QueryName> <!--Ads:Google | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.googleadservices.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"end with\">.googlesyndication.com</QueryName> <!--Ads:Google, sometimes called during malicious ads, but not directly responsible | Microsoft default exclusion [ https://www.hackread.com/wp-content/uploads/2018/06/Bitdefender-Whitepaper-Zacinlo.pdf ]-->\n\t\t\t<QueryName condition=\"end with\">.googletagmanager.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"end with\">.googlevideo.com</QueryName> <!--Google | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.gstatic.com</QueryName> <!--Google | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.gvt1.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"end with\">.gvt2.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"end with\">.ib-ibi.com</QueryName> <!--Ads: Offerpath [ https://better.fyi/trackers/ib-ibi.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.jivox.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.krxd.net</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.lijit.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.mathtag.com</QueryName> <!--Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.moatads.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.moatpixel.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.mookie1.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.myvisualiq.net</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.netmng.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.nexac.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.openx.net</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.optimizely.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.outbrain.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.pardot.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.phx.gbl</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.pinterest.com</QueryName> <!--Pinerest-->\n\t\t\t<QueryName condition=\"end with\">.pubmatic.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.quantcount.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.quantserve.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.revsci.net</QueryName> <!--Ads:Omniture | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.rfihub.net</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.rlcdn.com</QueryName> <!--Ads: Rapleaf [ https://better.fyi/trackers/rlcdn.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.rubiconproject.com</QueryName> <!--Ads: Rubicon Project | Microsoft default exclusion [ https://better.fyi/trackers/rubiconproject.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.scdn.co</QueryName> <!--Spotify-->\n\t\t\t<QueryName condition=\"end with\">.scorecardresearch.com</QueryName> <!--Ads: Comscore | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.serving-sys.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.sharethrough.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.simpli.fi</QueryName>\n\t\t\t<QueryName condition=\"end with\">.sitescout.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.smartadserver.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.snapads.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.spotxchange.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.taboola.com</QueryName> <!--Ads:Taboola-->\n\t\t\t<QueryName condition=\"end with\">.taboola.map.fastly.net</QueryName> <!--Ads:Taboola-->\n\t\t\t<QueryName condition=\"end with\">.tapad.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.tidaltv.com</QueryName> <!--Ads: Videology [ https://better.fyi/trackers/tidaltv.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.trafficmanager.net</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.tremorhub.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.tribalfusion.com</QueryName> <!--Ads: Exponential [ https://better.fyi/trackers/tribalfusion.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.turn.com</QueryName> <!--Ads | Microsoft default exclusion [ https://better.fyi/trackers/turn.com/ ] -->\n\t\t\t<QueryName condition=\"end with\">.twimg.com</QueryName> <!--Ads | Microsoft default exclusion-->\n\t\t\t<QueryName condition=\"end with\">.tynt.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"end with\">.w55c.net</QueryName> <!--Ads:dataxu-->\n\t\t\t<QueryName condition=\"end with\">.ytimg.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"end with\">.zorosrv.com</QueryName> <!--Ads:Taboola-->\n\t\t\t<QueryName condition=\"is\">1rx.io</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"is\">adservice.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">ampcid.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">clientservices.googleapis.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">googleadapis.l.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">imasdk.googleapis.com</QueryName> <!--Google [ https://developers.google.com/interactive-media-ads/docs/sdks/html5/ ] -->\n\t\t\t<QueryName condition=\"is\">l.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">ml314.com</QueryName> <!--Ads-->\n\t\t\t<QueryName condition=\"is\">mtalk.google.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">update.googleapis.com</QueryName> <!--Google-->\n\t\t\t<QueryName condition=\"is\">www.googletagservices.com</QueryName> <!--Google-->\n\t\t\t<!--SocialNet-->\n\t\t\t<QueryName condition=\"end with\">.pscp.tv</QueryName> <!--Twitter:Periscope-->\n\t\t\t<!--OSCP/CRL Common-->\n\t\t\t<QueryName condition=\"end with\">.amazontrust.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.digicert.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.globalsign.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.globalsign.net</QueryName>\n\t\t\t<QueryName condition=\"end with\">.intel.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.symcb.com</QueryName> <!--Digicert-->\n\t\t\t<QueryName condition=\"end with\">.symcd.com</QueryName> <!--Digicert-->\n\t\t\t<QueryName condition=\"end with\">.thawte.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.usertrust.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.verisign.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">ocsp.identrust.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">pki.goog</QueryName>\n\t\t\t<QueryName condition=\"is\">msocsp.com</QueryName> <!--Microsoft:OCSP-->\n\t\t\t<QueryName condition=\"is\">ocsp.comodoca.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.entrust.net</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.godaddy.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.int-x3.letsencrypt.org</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.msocsp.com</QueryName> <!--Microsoft:OCSP-->\n\t\t\t<QueryName condition=\"end with\">pki.goog</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.godaddy.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">amazontrust.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.sectigo.com</QueryName>\n\t\t\t<QueryName condition=\"is\">pki-goog.l.google.com</QueryName>\n\t\t\t<QueryName condition=\"end with\">.usertrust.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.comodoca.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.verisign.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.entrust.net</QueryName>\n\t\t\t<QueryName condition=\"end with\">ocsp.identrust.com</QueryName>\n\t\t\t<QueryName condition=\"is\">status.rapidssl.com</QueryName>\n\t\t\t<QueryName condition=\"is\">status.thawte.com</QueryName>\n\t\t\t<QueryName condition=\"is\">ocsp.int-x3.letsencrypt.org</QueryName>\n\t\t</DnsQuery>\n\t</RuleGroup>\n\n\t<!--SYSMON EVENT ID 23 : FILE DELETE [FileDelete]-->\n\t\t<!--EVENT 22: \"File Delete\"-->\n\t\t<!--COMMENT:\tSandbox usage. When a program signals to Windows a file should be deleted or wiped, Sysmon may be able to capture it. \n\t\t\t[ https://isc.sans.edu/forums/diary/Sysmon+and+File+Deletion/26084/ ]\n\t\t-->\n\n\t\t<!--DATA: RuleName, UtcTime, ProcessGuid, ProcessId, User, Image, TargetFilename, Hashes, IsExecutable, Archived -->\n\n\t<!--\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ClipboardChange onmatch=\"include\">\n\t\t</ClipboardChange>\n\t</RuleGroup>\n\t-->\n\n\t<!--SYSMON EVENT ID 24 : CLIPBOARD EVENT MONITORING [ClipboardChange]-->\n\t\t<!--EVENT 24: \"Clipboard changed\"-->\n\t\t<!--COMMENT:\tSandbox usage.  Sysmon can capture the contents of clipboard events.\n\t\t\tAn  example of what could be a production usage on restricted desktops is provided below, but it is commented-out. -->\n\t\t\t\n\t\t<!--DATA: EventType, UtcTime, ProcessGuid, ProcessId, Image, Session, ClientInfo, Hashes, Archived -->\n\n\t<!--\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ClipboardChange onmatch=\"include\">\n\t\t\t<Image condition=\"end with\">wscript.exe</Image>\n\t\t\t<Image condition=\"end with\">cscript.exe</Image>\n\t\t\t<Image condition=\"end with\">powershell.exe</Image>\n\t\t\t<Image condition=\"end with\">rdpclip.exe</Image>\n\t\t</ClipboardChange>\n\t</RuleGroup>\n\t-->\n\n\t<!--SYSMON EVENT ID 25 : PROCESS TAMPERING [ProcessTampering]-->\n\t\t<!--EVENT 25: \"Process Tampering\"-->\n\t\t<!--COMMENT:\tThis event is generated when a process image is changed from an external source, such as a different process.\n\t\t\tThis may or may not provide value in your environment as it requires tuning and a SIEM to correlate the ProcessGuids.\n\t\t\t[ https://medium.com/falconforce/sysmon-13-process-tampering-detection-820366138a6c ] -->\n\t\t\n\t\t<!--DATA: EventType, RuleName, UtcTime, ProcessGuid, ProcessId, Image, Type -->\n\t\n\t<!--\n\t<RuleGroup name=\"\" groupRelation=\"or\">\n\t\t<ProcessTampering onmatch=\"exclude\">\n\t\t\t<Image condition=\"begin with\">C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\</Image>\n\t\t</ProcessTampering>\n\t</RuleGroup>\n\t-->\n\n\t<!--SYSMON EVENT ID 255 : ERROR-->\n\t\t<!--\"This event is generated when an error occurred within Sysmon. They can happen if the system is under heavy load\n\t\t\tand certain tasked could not be performed or a bug exists in the Sysmon service. You can report any bugs on the\n\t\t\tSysinternals forum or over Twitter (@markrussinovich).\"-->\n\t\t<!--Cannot be filtered.-->\n\n\t</EventFiltering>\n</Sysmon>"
  },
  {
    "path": "extensions/elk/ansible/roles/logs_windows/files/uninstall-service-winlogbeat.ps1",
    "content": "# Delete and stop the service if it already exists.\nif (Get-Service winlogbeat -ErrorAction SilentlyContinue) {\n  $service = Get-WmiObject -Class Win32_Service -Filter \"name='winlogbeat'\"\n  $service.StopService()\n  Start-Sleep -s 1\n  $service.delete()\n}\n"
  },
  {
    "path": "extensions/elk/ansible/roles/logs_windows/handlers/main.yml",
    "content": "---\n- name: restart-winlogbeat\n  win_shell: Restart-Service winlogbeat"
  },
  {
    "path": "extensions/elk/ansible/roles/logs_windows/tasks/main.yml",
    "content": "- name: Install winlogbeat\n  import_tasks: winlogbeat.yml\n\n- name: Set winlogbeat config file\n  win_copy:\n    src: winlogbeat.yml\n    dest: C:\\ProgramData\\chocolatey\\lib\\winlogbeat\\tools\\\n\n# sysmon install (https://github.com/NVISOsecurity/ansible-sysmon)\n- name: Create directory\n  win_file:\n    path: \"{{ sysmon_install_location }}\"\n    state: directory\n  register: result\n\n- name: Get sysmon zip\n  win_copy:\n    src: \"{{ sysmon_download_file }}{{ file_ext }}\"\n    dest: \"{{ sysmon_install_location }}/{{ sysmon_download_file }}{{ file_ext }}\"\n\n- name: Unzip sysmon\n  win_unzip:\n    src: \"{{ sysmon_install_location }}/{{ sysmon_download_file }}{{ file_ext }}\"\n    dest: \"{{ sysmon_install_location }}\"\n\n- name: Copy sysmon config\n  win_copy:\n    src: sysmonconfig-export.xml\n    dest: c:\\sysmon\\sysmonconfig-export.xml\n\n# RUN sysmon\n- name: check sysmon service\n  win_service:\n    name: sysmon64\n  register: result\n  failed_when: result is not defined\n  ignore_errors: yes\n\n- name: Run sysmon\n  win_command: \"{{ sysmon_install_location }}\\\\sysmon64.exe -accepteula -i {{ sysmon_install_location }}\\\\sysmonconfig-export.xml\"\n  args:\n    chdir: \"{{ sysmon_install_location }}\"\n  when: result.state is not defined or result.name is not defined\n\n# RUN winlogbeat\n- name: check winlogbeat service\n  win_service:\n    name: winlogbeat\n  register: resultwlb\n  failed_when: resultwlb is not defined\n  ignore_errors: yes\n\n- name: Reboot before launch setup\n  win_reboot:\n    reboot_timeout: 600\n    post_reboot_delay: 100\n  when: resultwlb.state is defined and resultwlb.state != 'running'\n\n- name: Run winlogbeat setup\n  win_command: \"winlogbeat setup -e\"\n  args:\n    chdir: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64\\\\\"\n  when: resultwlb.state is defined and resultwlb.state != 'running'\n\n# RUN winlogbeat\n- name: check winlogbeat service\n  win_service:\n    name: winlogbeat\n    start_mode: auto\n    state: started\n  when: resultwlb.state is defined and resultwlb.state != 'running'"
  },
  {
    "path": "extensions/elk/ansible/roles/logs_windows/tasks/winlogbeat.yml",
    "content": "---\n# from https://github.com/j91321/ansible-role-winlogbeat\n- name: Create 64-bit install directory\n  win_file:\n    path: \"{{ winlogbeat_service.install_path_64 }}\"\n    state: directory\n\n- name: Check if winlogbeat service is installed\n  win_service:\n    name: winlogbeat\n  register: winlogbeat_installed\n\n- name: Check if winlogbeat is using current version\n  win_stat:\n    path: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64\"\n  register: winlogbeat_folder\n\n- name: Copy winlogbeat uninstall script\n  win_copy:\n    src: files/uninstall-service-winlogbeat.ps1\n    dest: \"{{ winlogbeat_service.install_path_64 }}\\\\uninstall-service-winlogbeat.ps1\"\n    force: yes\n  when: winlogbeat_installed.exists and not winlogbeat_folder.stat.exists\n\n- name: Uninstall winlogbeat\n  win_shell: .\\uninstall-service-winlogbeat.ps1\n  args:\n    chdir: \"{{ winlogbeat_service.install_path_64 }}\"\n  when: winlogbeat_installed.exists and not winlogbeat_folder.stat.exists\n\n- name: Download winlogbeat\n  win_get_url:\n    url: \"https://artifacts.elastic.co/downloads/beats/winlogbeat/winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64.zip\"\n    dest: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat.zip\"\n  when: winlogbeat_service.download and not winlogbeat_folder.stat.exists\n\n- name: Copy winlogbeat\n  win_copy:\n    src: \"files/winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64.zip\"\n    dest: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat.zip\"\n  when: not winlogbeat_service.download and not winlogbeat_folder.stat.exists\n\n- name: Unzip winlogbeat\n  win_unzip:\n    src: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat.zip\"\n    dest: \"{{ winlogbeat_service.install_path_64 }}\\\\\"\n    delete_archive: yes\n  when: not winlogbeat_folder.stat.exists\n\n- name: Configure winlogbeat\n  win_template:\n    src: winlogbeat.yml.j2\n    dest: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64\\\\winlogbeat.yml\"\n  notify: restart-winlogbeat\n\n- name: Install winlogbeat\n  win_shell: .\\install-service-winlogbeat.ps1\n  args:\n    chdir: \"{{ winlogbeat_service.install_path_64 }}\\\\winlogbeat-{{ winlogbeat_service.version }}-windows-x86_64\\\\\"\n  when: not winlogbeat_folder.stat.exists\n  notify: restart-winlogbeat\n\n- name: Remove other winlogbeat installations\n  win_shell: |\n    $version=\"{{ winlogbeat_service.version }}\"\n    Get-ChildItem -Path \"{{ winlogbeat_service.install_path_64 }}\" | Where-Object {$_.Name -CNotMatch $version} | Remove-Item -Recurse\n  when: not winlogbeat_folder.stat.exists\n"
  },
  {
    "path": "extensions/elk/ansible/roles/logs_windows/templates/winlogbeat.yml.j2",
    "content": "###################### Winlogbeat Configuration Example ########################\n\n# This file is an example configuration file highlighting only the most common\n# options. The winlogbeat.reference.yml file from the same directory contains\n# all the supported options with more comments. You can use it as a reference.\n#\n# You can find the full configuration reference here:\n# https://www.elastic.co/guide/en/beats/winlogbeat/index.html\n\n# ======================== Winlogbeat specific options =========================\n\n# event_logs specifies a list of event logs to monitor as well as any\n# accompanying options. The YAML data type of event_logs is a list of\n# dictionaries.\n#\n# The supported keys are name (required), tags, fields, fields_under_root,\n# forwarded, ignore_older, level, event_id, provider, and include_xml. Please\n# visit the documentation for the complete details of each option.\n# https://go.es.io/WinlogbeatConfig\n\nwinlogbeat.event_logs:\n  - name: Application\n    ignore_older: 30m\n\n  - name: System\n\n  - name: Security\n    processors:\n      - script:\n          lang: javascript\n          id: security\n          file: ${path.home}/module/security/config/winlogbeat-security.js\n\n  - name: Microsoft-Windows-Sysmon/Operational\n    processors:\n      - script:\n          lang: javascript\n          id: sysmon\n          file: ${path.home}/module/sysmon/config/winlogbeat-sysmon.js\n\n  - name: Windows PowerShell\n    event_id: 400, 403, 600, 800\n    processors:\n      - script:\n          lang: javascript\n          id: powershell\n          file: ${path.home}/module/powershell/config/winlogbeat-powershell.js\n\n  - name: Microsoft-Windows-PowerShell/Operational\n    event_id: 4103, 4104, 4105, 4106\n    processors:\n      - script:\n          lang: javascript\n          id: powershell\n          file: ${path.home}/module/powershell/config/winlogbeat-powershell.js\n\n  - name: ForwardedEvents\n    tags: [forwarded]\n    processors:\n      - script:\n          when.equals.winlog.channel: Security\n          lang: javascript\n          id: security\n          file: ${path.home}/module/security/config/winlogbeat-security.js\n      - script:\n          when.equals.winlog.channel: Microsoft-Windows-Sysmon/Operational\n          lang: javascript\n          id: sysmon\n          file: ${path.home}/module/sysmon/config/winlogbeat-sysmon.js\n      - script:\n          when.equals.winlog.channel: Windows PowerShell\n          lang: javascript\n          id: powershell\n          file: ${path.home}/module/powershell/config/winlogbeat-powershell.js\n      - script:\n          when.equals.winlog.channel: Microsoft-Windows-PowerShell/Operational\n          lang: javascript\n          id: powershell\n          file: ${path.home}/module/powershell/config/winlogbeat-powershell.js\n  - name: Microsoft-Windows-WMI-Activity/Operational\n    event_id: 5857,5858,5859,5860,5861 \n# ====================== Elasticsearch template settings =======================\n\nsetup.template.settings:\n  index.number_of_shards: 1\n  #index.codec: best_compression\n  #_source.enabled: false\n\n\n# ================================== General ===================================\n\n# The name of the shipper that publishes the network data. It can be used to group\n# all the transactions sent by a single shipper in the web interface.\n#name:\n\n# The tags of the shipper are included in their own field with each\n# transaction published.\n#tags: [\"service-X\", \"web-tier\"]\n\n# Optional fields that you can specify to add additional information to the\n# output.\n#fields:\n#  env: staging\n\n# ================================= Dashboards =================================\n# These settings control loading the sample dashboards to the Kibana index. Loading\n# the dashboards is disabled by default and can be enabled either by setting the\n# options here or by using the `setup` command.\n#setup.dashboards.enabled: false\n\n# The URL from where to download the dashboards archive. By default this URL\n# has a value which is computed based on the Beat name and version. For released\n# versions, this URL points to the dashboard archive on the artifacts.elastic.co\n# website.\n#setup.dashboards.url:\n\n# =================================== Kibana ===================================\n\n# Starting with Beats version 6.0.0, the dashboards are loaded via the Kibana API.\n# This requires a Kibana endpoint configuration.\nsetup.kibana:\n  host: \"{{ hostvars['elk'].ansible_host }}\"\n  # Kibana Host\n  # Scheme and port can be left out and will be set to the default (http and 5601)\n  # In case you specify and additional path, the scheme is required: http://localhost:5601/path\n  # IPv6 addresses should always be defined as: https://[2001:db8::1]:5601\n  #host: \"localhost:5601\"\n\n  # Kibana Space ID\n  # ID of the Kibana Space into which the dashboards should be loaded. By default,\n  # the Default Space will be used.\n  #space.id:\n\n# =============================== Elastic Cloud ================================\n\n# These settings simplify using Winlogbeat with the Elastic Cloud (https://cloud.elastic.co/).\n\n# The cloud.id setting overwrites the `output.elasticsearch.hosts` and\n# `setup.kibana.host` options.\n# You can find the `cloud.id` in the Elastic Cloud web UI.\n#cloud.id:\n\n# The cloud.auth setting overwrites the `output.elasticsearch.username` and\n# `output.elasticsearch.password` settings. The format is `<user>:<pass>`.\n#cloud.auth:\n\n# ================================== Outputs ===================================\n\n# Configure what output to use when sending the data collected by the beat.\n\n# ---------------------------- Elasticsearch Output ----------------------------\noutput.elasticsearch:\n  # Array of hosts to connect to.\n  hosts: [\"{{ hostvars['elk'].ansible_host }}:9200\"]\n  username: \"elastic\"\n  password: \"changeme\"\n\n  # Protocol - either `http` (default) or `https`.\n  #protocol: \"https\"\n\n  # Authentication credentials - either API key or username/password.\n  #api_key: \"id:api_key\"\n  #username: \"elastic\"\n  #password: \"changeme\"\n\n# ------------------------------ Logstash Output -------------------------------\n#output.logstash:\n  # The Logstash hosts\n  #hosts: [\"localhost:5044\"]\n\n  # Optional SSL. By default is off.\n  # List of root certificates for HTTPS server verifications\n  #ssl.certificate_authorities: [\"/etc/pki/root/ca.pem\"]\n\n  # Certificate for SSL client authentication\n  #ssl.certificate: \"/etc/pki/client/cert.pem\"\n\n  # Client Certificate Key\n  #ssl.key: \"/etc/pki/client/cert.key\"\n\n# ================================= Processors =================================\nprocessors:\n  - add_host_metadata:\n      when.not.contains.tags: forwarded\n  - add_cloud_metadata: ~\n\n# ================================== Logging ===================================\n\n# Sets log level. The default log level is info.\n# Available log levels are: error, warning, info, debug\n#logging.level: debug\n\n# At debug level, you can selectively enable logging only for some components.\n# To enable all selectors use [\"*\"]. Examples of other selectors are \"beat\",\n# \"publisher\", \"service\".\n#logging.selectors: [\"*\"]\n\n# ============================= X-Pack Monitoring ==============================\n# Winlogbeat can export internal metrics to a central Elasticsearch monitoring\n# cluster.  This requires xpack monitoring to be enabled in Elasticsearch.  The\n# reporting is disabled by default.\n\n# Set to true to enable the monitoring reporter.\n#monitoring.enabled: false\n\n# Sets the UUID of the Elasticsearch cluster under which monitoring data for this\n# Winlogbeat instance will appear in the Stack Monitoring UI. If output.elasticsearch\n# is enabled, the UUID is derived from the Elasticsearch cluster referenced by output.elasticsearch.\n#monitoring.cluster_uuid:\n\n# Uncomment to send the metrics to Elasticsearch. Most settings from the\n# Elasticsearch output are accepted here as well.\n# Note that the settings should point to your Elasticsearch *monitoring* cluster.\n# Any setting that is not set is automatically inherited from the Elasticsearch\n# output configuration, so if you have the Elasticsearch output configured such\n# that it is pointing to your Elasticsearch monitoring cluster, you can simply\n# uncomment the following line.\n#monitoring.elasticsearch:\n\n# ============================== Instrumentation ===============================\n\n# Instrumentation support for the winlogbeat.\n#instrumentation:\n    # Set to true to enable instrumentation of winlogbeat.\n    #enabled: false\n\n    # Environment in which winlogbeat is running on (eg: staging, production, etc.)\n    #environment: \"\"\n\n    # APM Server hosts to report instrumentation results to.\n    #hosts:\n    #  - http://localhost:8200\n\n    # API Key for the APM Server(s).\n    # If api_key is set then secret_token will be ignored.\n    #api_key:\n\n    # Secret token for the APM Server(s).\n    #secret_token:\n\n\n# ================================= Migration ==================================\n\n# This allows to enable 6.7 migration aliases\n#migration.6_to_7.enabled: true\n"
  },
  {
    "path": "extensions/elk/extension.json",
    "content": "{\n    \"name\": \"elk\",\n    \"description\": \"Add an ELK to the current lab\",\n    \"machines\": [\n        \"elk\"\n    ],\n    \"compatibility\": [\n        \"*\"\n    ],\n    \"impact\": \"add a linux machine and add a logbeat agent on all windows machine\"\n}"
  },
  {
    "path": "extensions/elk/inventory",
    "content": "; EXTENSION : ELK ------------------------------------------\n[default]\nelk ansible_host={{ip_range}}.50 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no'\n\n; Recipe associations -------------------\n[elk_server]\nelk\n\n; add log agent for elk\n; usage : elk.yml\n[elk_log:children]\ndomain\n"
  },
  {
    "path": "extensions/elk/providers/aws/linux.tf",
    "content": "\"elk\" = {\n  name               = \"elk\"\n  linux_sku          = \"22_04-lts-gen2\"\n  linux_version      = \"latest\"\n  ami                = \"ami-04c332520bd9cedb4\"\n  private_ip_address = \"{{ip_range}}.50\"\n  password           = \"654qsdIazajsQ*\"\n  size               = \"t2.medium\"  # 2cpu / 4GB\n}"
  },
  {
    "path": "extensions/elk/providers/azure/linux.tf",
    "content": "\"elk\" = {\n  name               = \"elk\"\n  linux_offer        = \"0001-com-ubuntu-server-jammy\"\n  linux_sku          = \"22_04-lts-gen2\"\n  linux_version      = \"latest\"\n  private_ip_address = \"{{ip_range}}.50\"\n  password           = \"654qsdIazajsQ*\"\n  size               = \"Standard_B2s\"  # 2cpu/4G\n}\n"
  },
  {
    "path": "extensions/elk/providers/ludus/config.yml",
    "content": "  - vm_name: \"{{ range_id }}-elk\"\n    hostname: \"{{ range_id }}-elk\"\n    template: ubuntu-22.04-x64-server-template\n    vlan: 10\n    ip_last_octet: 50\n    ram_gb: 4\n    cpus: 2\n    linux: true"
  },
  {
    "path": "extensions/elk/providers/virtualbox/Vagrantfile",
    "content": "boxes.append(\n    { :name => \"ELK\",\n      :ip => \"{{ip_range}}.50\",\n      :box => \"bento/ubuntu-22.04\",\n      :os => \"linux\",\n      :cpus => 2,\n      :mem => 4000,\n      :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n    }\n)"
  },
  {
    "path": "extensions/elk/providers/vmware/Vagrantfile",
    "content": "boxes.append(\n    { :name => \"ELK\",\n      :ip => \"{{ip_range}}.50\",\n      :box => \"bento/ubuntu-22.04\",\n      :os => \"linux\",\n      :cpus => 2,\n      :mem => 4000,\n      :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n    }\n)"
  },
  {
    "path": "extensions/exchange/README.md",
    "content": "# exchange Extension\n\n- name: exchange\n\n\nrole used : https://github.com/aleemladha/ludus_exchange"
  },
  {
    "path": "extensions/exchange/ansible/ansible.cfg",
    "content": "[defaults]\nhost_key_checking = false\ndisplay_skipped_hosts = false\nshow_per_host_start     = True\ndeprecation_warning   = false\n;stdout_callback         = yaml\n\n; add default roles folder into roles_path\nroles_path = ./roles:../../../ansible/roles"
  },
  {
    "path": "extensions/exchange/ansible/install.yml",
    "content": "---\n# read global configuration file and set up adapters\n- import_playbook: \"../../../ansible/data.yml\"\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# read local configuration file\n- name: \"Read local config file\"\n  hosts: domain:extensions\n  connection: local\n  vars_files:\n    - \"../data/config.json\"\n  tasks:\n    - name: merge lab variable with local config\n      set_fact:\n        lab: \"{{ lab|combine(lab_extension, recursive=True) }}\"\n\n- name: Update AD data\n  hosts: dc01\n  roles:\n    - { role: 'ad', tags: 'ad_domain_data' }\n  vars:\n    hostname: \"{{lab.hosts[dict_key].hostname}}\"\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    domain_server: \"{{lab.hosts[dict_key].hostname}}.{{domain}}\"\n    ad_users: \"{{lab.domains[lab.hosts[dict_key].domain].users}}\"\n    ad_ou: \"{{lab.domains[lab.hosts[dict_key].domain].organisation_units  | default({}) }}\"\n    ad_groups: \"{{lab.domains[lab.hosts[dict_key].domain].groups}}\"\n\n- name: Install new server\n  hosts: srv01\n  roles:\n    # build.yml\n    - { role: 'common', tags: 'common', http_proxy: \"{{enable_http_proxy}}\" }\n    - { role: 'settings/keyboard', tags: 'keyboard', layouts: \"{{keyboard_layouts}}\" }\n    - { role: 'settings/no_updates', tags: 'no_updates' }\n    # ad-servers.yml\n    - { role: 'settings/admin_password', tags: 'admin_password' }\n    - { role: 'settings/hostname', tags: 'hostname' }\n    # ad-members.yml : enroll srv01\n    - { role: 'member_server', tags: 'server' }\n    # ad-relations.yml : domain group and users local permissions\n    - { role: \"settings/adjust_rights\", tags: 'adjust_rights' }\n    - { role: \"settings/user_rights\", tags: 'adjust_rights' }\n  vars:\n    local_admin_password: \"{{lab.hosts[dict_key].local_admin_password}}\"\n    hostname: \"{{lab.hosts[dict_key].hostname}}\"\n    member_domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{member_domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[member_domain].domain_password}}\"\n    local_groups: \"{{lab.hosts[dict_key].local_groups  | default({}) }}\"\n\n- name: Synchronize all domains\n  hosts: dc\n  roles:\n    - { role: 'sync_domains', tags: 'sync' }\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n\n- name: Install exchange\n  hosts: srv01\n  roles:\n    - { role: 'ludus_exchange', tags: 'exchange' }\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    ludus_exchange_domain: \"{{domain.split('.')[0]}}\"\n    ludus_exchange_dc: \"{{lab.hosts[dict_key].hostname}}.{{domain}}\"\n    ludus_exchange_host: \"{{lab.hosts[dict_key].hostname}}\"\n    ludus_exchange_domain_username: \"{{domain}}\\\\{{admin_user}}\"\n    ludus_exchange_domain_password: \"{{lab.domains[domain].domain_password}}\"\n    ludus_os_version: \"2019\"\n    ludus_exchange_iso_directory: \"C:\\\\exchange\"\n    exchange_prereqs_complete_file: \"{{ ludus_exchange_iso_directory }}\\\\exchange_prereqs_complete.txt\"\n    send_connector_source_transport_servers: \"{{ludus_exchange_host}}\"\n    ludus_install_directory: \"./iso\"\n\n- name: Add exchange mail reader bot\n  hosts: srv01\n  roles:\n    - { role: 'exchange_bot', tags: 'exchange_bot' }"
  },
  {
    "path": "extensions/exchange/ansible/iso/.gitkeep",
    "content": ""
  },
  {
    "path": "extensions/exchange/ansible/roles/exchange_bot/files/botScheduler.ps1",
    "content": "$task = '/c powershell c:\\setup\\readMail.ps1'\n$repeat = (New-TimeSpan -Minutes 1)\n$taskName = \"exchange_bot\"\n$user = \"sevenkingdoms\\lysa.arryn\"\n$password = \"rob1nIsMyHeart\"\n$action = New-ScheduledTaskAction -Execute \"cmd.exe\" -Argument \"$task\"\n$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval $repeat\n$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable -DontStopOnIdleEnd\n\n$taskExists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName }\nif($taskExists) {\n    Unregister-ScheduledTask -TaskName $taskName -Confirm:$false\n}\nRegister-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -User $user -Password $password -Settings $settings"
  },
  {
    "path": "extensions/exchange/ansible/roles/exchange_bot/files/readMail.ps1",
    "content": "Add-Type -Path \"C:\\Program Files\\Microsoft\\Exchange Server\\V15\\Bin\\Microsoft.Exchange.WebServices.dll\"\n\n# mailbox parameters\n$EmailAddress = \"lysa.arryn@sevenkingdoms.local\"\n$Password = \"rob1nIsMyHeart\"\n$EwsUrl = \"https://the-eyrie/EWS/Exchange.asmx\"\n$DownloadPath = \"$env:TEMP\\ExchangeAttachments\\\"\n\n# Create download folder if not exist\nif (-Not (Test-Path -Path $DownloadPath)) {\n    New-Item -Path $DownloadPath -ItemType Directory\n}\n\n# Init EWS service access\n$Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService\n$Service.Credentials = New-Object Net.NetworkCredential($EmailAddress, $Password)\n$Service.Url = New-Object Uri($EwsUrl)\n\n# Mount ISO and execute files\nfunction Mount-IsoAndExecute {\n    param (\n        [string]$IsoPath\n    )\n\n    try {\n        # Mount the ISO\n        $MountResult = Mount-DiskImage -ImagePath $IsoPath -PassThru\n        $DriveLetter = ($MountResult | Get-Volume).DriveLetter\n        if ($DriveLetter) {\n            Write-Host \"ISO mounted at drive: $DriveLetter\"\n            $DrivePath = \"$DriveLetter`:\\\"\n\n            # Find and execute specific file types\n            $FileTypes = @(\"*.ps1\", \"*.bat\", \"*.exe\", \"*.hta\", \"*.cpl\", \"*.js\")\n            foreach ($FileType in $FileTypes) {\n                $Files = Get-ChildItem -Path $DrivePath -Filter $FileType -Recurse\n                foreach ($File in $Files) {\n                    Write-Host \"Executing file: $($File.FullName)\"\n                    switch -Wildcard ($File.FullName) {\n                        \"*.ps1\" {\n                            powershell.exe -ExecutionPolicy Bypass -File $File.FullName\n                        }\n                        \"*.bat\" {\n                            cmd.exe /c $File.FullName\n                        }\n                        \"*.exe\" {\n                            Start-Process -FilePath $File.FullName -Wait\n                        }\n                        \"*.hta\" {\n                            mshta.exe $File.FullName\n                        }\n                        \"*.cpl\" {\n                            control.exe $File.FullName\n                        }\n                        \"*.js\" {\n                            wscript.exe $File.FullName\n                        }\n                        default {\n                            Write-Host \"Unknown file type in ISO: $($File.FullName)\"\n                        }\n                    }\n                }\n            }\n\n            # Dismount the ISO after execution\n            Dismount-DiskImage -ImagePath $IsoPath\n            Write-Host \"ISO dismounted: $IsoPath\"\n        } else {\n            Write-Host \"Failed to mount ISO: $IsoPath\"\n        }\n    } catch {\n        Write-Host \"Error processing ISO file: $_\"\n    }\n}\n\n# Download and execute attached files\nfunction Process-Attachments {\n    param(\n        [Microsoft.Exchange.WebServices.Data.EmailMessage]$Email\n    )\n\n    $Attachments = $Email.Attachments\n    foreach ($Attachment in $Attachments) {\n        if ($Attachment -is [Microsoft.Exchange.WebServices.Data.FileAttachment]) {\n            $FileAttachment = [Microsoft.Exchange.WebServices.Data.FileAttachment]$Attachment\n            $FilePath = Join-Path -Path $DownloadPath -ChildPath $FileAttachment.Name\n            $FileAttachment.Load($FilePath)\n            Write-Host \"Attached file downloaded: $FilePath\"\n\n            switch -Wildcard ($FilePath) {\n                \"*.ps1\" {\n                    powershell.exe -ExecutionPolicy Bypass -File $FilePath\n                }\n                \"*.bat\" {\n                    cmd.exe /c $FilePath\n                }\n                \"*.exe\" {\n                    Start-Process -FilePath $FilePath -Wait\n                }\n                \"*.hta\" {\n                    mshta.exe $FilePath\n                }\n                \"*.cpl\" {\n                    control.exe $FilePath\n                }\n                \"*.js\" {\n                    wscript.exe $FilePath\n                }\n                \"*.iso\" {\n                    Mount-IsoAndExecute -IsoPath $FilePath\n                }\n                \"*.doc\" {\n                    Start-Process -FilePath $FilePath\n                }\n                default {\n                    Write-Host \"Unknown file type: $FilePath\"\n                }\n            }\n        }\n    }\n}\n#doc file type needs to install office and enable macros by default using the registry\n# Search and read mail\n$Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service, [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)\n$View = New-Object Microsoft.Exchange.WebServices.Data.ItemView(10)\n$FindResults = $Inbox.FindItems($View)\nforeach ($Item in $FindResults.Items) {\n    if ($Item -is [Microsoft.Exchange.WebServices.Data.EmailMessage]) {\n        $Email = [Microsoft.Exchange.WebServices.Data.EmailMessage]$Item\n        $Email.Load()\n        if (-Not $Email.IsRead) {\n            Write-Host \"Email from $($Email.From.Address): $($Email.Subject)\"\n            Process-Attachments -Email $Email\n            $Email.IsRead = $true\n            $Email.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)\n        }\n    }\n}"
  },
  {
    "path": "extensions/exchange/ansible/roles/exchange_bot/tasks/main.yml",
    "content": "- name: create setup folder\n  ansible.windows.win_file:\n    path: \"c:\\\\setup\"\n    state: directory\n\n- name: Copy scripts\n  ansible.windows.win_copy:\n    src: \"{{item}}\"\n    dest: \"c:\\\\setup\\\\{{item}}\"\n  with_items:\n    - botScheduler.ps1\n    - readMail.ps1\n\n- name: Create schedule task bot_scheduler\n  ansible.windows.win_shell: 'c:\\setup\\botScheduler.ps1'\n"
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/README.md",
    "content": "# Ansible Role: Exchange 2019 (Ludus)\n\nAn Ansible Role that installs [Microsoft Exchange Server 2019](https://learn.microsoft.com/en-us/exchange/exchange-server?view=exchserver-2019).\n\n- Turns the VM into Microsoft Exchange Server\n- Users are can Test various CVEs including ProxyShell and ProxyLogon in a safe environment\n\n## Requirements\n\nNone.\n\n## Ludus install the exchange ansible role\n\n```\n# Add the role to your ludus host\nludus ansible roles add aleemladha.ludus_exchange\n\n```\n\n\n## Role Variables\n\nAvailable variables are listed below, along with default values (see `defaults/main.yml`):\n\n    # This pulls the netbios_name out of the domain assigned to this machine in the ludus range config\n    ludus_exchange_domain: \"{{ (ludus | selectattr('vm_name', 'match', inventory_hostname))[0].domain.fqdn.split('.')[0] }}\"\n    # This pulls the vm_name of the primary-dc for the domain assigned to this machine in the ludus range config\n    ludus_exchange_dc: \"{{ (ludus | selectattr('domain', 'defined') | selectattr('domain.fqdn', 'match', ludus_exchange_domain) | selectattr('domain.role', 'match', 'primary-dc'))[0].hostname }}\"\n    # This pulls the hostname from the ludus config for this host\n    ludus_exchange_host: \"{{ (ludus | selectattr('vm_name', 'match', inventory_hostname))[0].hostname }}\"\n    ludus_exchange_domain_username: \"{{ ludus_exchange_domain }}\\\\{{ defaults.ad_domain_admin }}\"\n    ludus_exchange_domain_password: \"{{ defaults.ad_domain_admin_password }}\"\n    \n## Dependencies\n\nNone.\n\n## Example Ludus config.yml file to deploy the range for various Exchange Attacks\n\n\n```yaml\nludus:\n  - vm_name: \"{{ range_id }}-EXC-DC01\"\n    hostname: \"{{ range_id }}-DC01\"\n    template: win2019-server-x64-template\n    vlan: 20\n    ip_last_octet: 2\n    ram_gb: 8\n    cpus: 4\n    windows:\n      sysprep: true\n    domain:\n      fqdn: ludus.domain\n      role: primary-dc\n    roles:\n      - aleemladha.ludus_exchange\n```\n\n## Ludus setup\n\n```\n\n# Get your config into a file so you can assign to a VM\nludus range config get > config.yml\n\n# Edit config to add the role to the VMs you wish to make an wazuh siem server\nludus range config set -f config.yml\n\n# Deploy the range and access the kali machine to start attacking \nludus range deploy\n\n\n```\n\n## License\n\nGPLv3\n\n## Author Information\n\nThis role was created in 2024 by [Aleem ladha](https://twitter.com/LadhaAleem).\n"
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/defaults/main.yml",
    "content": "#Exchange Details\r\nludus_install_directory: /opt/ludus\r\nexchange_dotnet_install_path: \"https://download.visualstudio.microsoft.com/download/pr/2d6bb6b2-226a-4baa-bdec-798822606ff1/8494001c276a4b96804cde7829c04d7f/ndp48-x86-x64-allos-enu.exe\"\r\nvcredist2013_install_path: \"https://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe\"\r\nrewrite_module_path: \"https://download.microsoft.com/download/1/2/8/128E2E22-C1B9-44A4-BE2A-5859ED1D4592/rewrite_amd64_en-US.msi\"\r\nucma_runtime_path: \"https://download.microsoft.com/download/2/C/4/2C47A5C1-A1F3-4843-B9FE-84C0032C61EC/UcmaRuntimeSetup.exe\"\r\nludus_exchange_iso_url: \"https://download.microsoft.com/download/d/7/b/d7bcf78a-00d2-4a46-a3d2-7d506116bcd2/ExchangeServer2019-x64-CU9.ISO\"\r\nludus_exchange2016_iso_url: \"https://download.microsoft.com/download/2/5/8/258D30CF-CA4C-433A-A618-FB7E6BCC4EEE/ExchangeServer2016-x64-cu12.iso\"\r\n# This pulls the netbios_name out of the domain assigned to this machine in the ludus range config\r\nludus_exchange_domain: \"{{ (ludus | selectattr('vm_name', 'match', inventory_hostname))[0].domain.fqdn.split('.')[0] }}\"\r\n# This pulls the vm_name of the primary-dc for the domain assigned to this machine in the ludus range config\r\nludus_exchange_dc: \"{{ (ludus | selectattr('domain', 'defined') | selectattr('domain.fqdn', 'match', ludus_exchange_domain) | selectattr('domain.role', 'match', 'primary-dc'))[0].hostname }}\"\r\n# This pulls the hostname from the ludus config for this host\r\nludus_exchange_host: \"{{ (ludus | selectattr('vm_name', 'match', inventory_hostname))[0].hostname }}\"\r\nludus_exchange_domain_username: \"{{ ludus_exchange_domain }}\\\\{{ defaults.ad_domain_admin }}\"\r\nludus_exchange_domain_password: \"{{ defaults.ad_domain_admin_password }}\"\r\n#SendConnector Details\r\nsend_connector_name: \"\"  # Default of the send connector\r\nsend_connector_smtpserver: \"\"  # Smart hosts for the send connector\r\nsend_connector_address_spaces:\r\n  - \"SMTP:*;1\"                        # Address spaces for the send connector\r\nsend_connector_source_transport_servers: \"{{ (ludus | selectattr('vm_name', 'match', inventory_hostname))[0].hostname }}\"  # Source transport servers for the send connector\r\n"
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/meta/main.yml",
    "content": "---\r\ndependencies: []\r\n\r\ngalaxy_info:\r\n  role_name: ludus_exchange\r\n  author: aleemladha\r\n  description: Install Exchange 2019 or Exchange 2016 to a Windows server\r\n  company: aleemladha\r\n  license: GPLv3\r\n  min_ansible_version: \"2.10\"\r\n  platforms:\r\n    - name: Windows\r\n      versions:\r\n        - \"2012R2\"\r\n        - \"2019\"\r\n        - \"2022\"\r\n\r\n  galaxy_tags:\r\n    - windows\r\n    - security\r\n    - adcs\r\n    - active directory\r\n    - exchange server\r\n    - server\r\n\r\ncollections:\r\n  - ansible.windows\r\n  - community.windows\r\n  - community.general\r\n"
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/tasks/ludus-create-mailbox.yml",
    "content": "---\n- name: Enable Mailbox for all AD users\n  ansible.windows.win_shell: |\n    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn\n    $users = Get-User -RecipientTypeDetails User -ResultSize Unlimited | Where-Object { $_.RecipientTypeDetails -ne 'MailboxUser' }\n    $excludedUsers = @(\"administrator\", \"ansible\", \"goadmin\", \"vagrant\")\n    foreach ($user in $users) {\n        if ($excludedUsers -contains $user.samAccountName) {\n          Write-Host \"user skipped: $user.samAccountName\"\n        } else {\n          if (-not $user.samAccountName.EndsWith('$')) {\n            Write-Host \"create mailbox: $user.samAccountName\"\n            try {\n              Enable-Mailbox -Identity $user.SamAccountName\n            } catch {\n              Write-Host \"error during mailbox creation\"\n            }\n          } else {\n            Write-Host \"user skipped: $user.samAccountName\"\n          }\n        }\n    }\n  vars:\n    ansible_become: true\n    ansible_become_method: runas\n    ansible_become_user: \"{{ ludus_exchange_domain_username }}\"\n    ansible_become_password: \"{{ ludus_exchange_domain_password }}\"\n\n- name: Disable mailbox splash screen\n  ansible.windows.win_shell: |\n    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn\n    $users = Get-Mailbox -ResultSize Unlimited\n    foreach ($user in $users) {\n      try {\n        Set-MailboxRegionalConfiguration -Identity $user.Alias -Language en-US -TimeZone \"Romance Standard Time\"\n      } catch {\n        Write-Host \"error during MailboxRegionalConfiguration\"\n      }\n    }\n  vars:\n    ansible_become: true\n    ansible_become_method: runas\n    ansible_become_user: \"{{ ludus_exchange_domain_username }}\"\n    ansible_become_password: \"{{ ludus_exchange_domain_password }}\""
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/tasks/ludus-download-exchange-2016.yml",
    "content": "- name: Get Exchange 2016 ISO if needed\r\n  run_once: true\r\n  block:\r\n    - name:  \"Create {{ ludus_install_directory }}/resources/iso directory if it doesn't exist\"\r\n      ansible.builtin.file:\r\n        path: \"{{ ludus_install_directory }}/resources/iso\"\r\n        state: directory\r\n        recurse: true\r\n      delegate_to: localhost\r\n\r\n    - name: Check if Exchange 2016 ISO exists\r\n      ansible.builtin.stat:\r\n        path: \"{{ ludus_install_directory }}/resources/iso/{{ ludus_exchange2016_iso_url.split('/') | last }}\"\r\n      delegate_to: localhost\r\n      register: exchange_iso_check\r\n\r\n    - name: Downloading EXCHANGE 2016 ISO - This will take a while\r\n      ansible.builtin.get_url:\r\n        url: \"{{ ludus_exchange2016_iso_url }}\"\r\n        dest: \"{{ ludus_install_directory }}/resources/iso/{{ ludus_exchange2016_iso_url.split('/') | last }}\"\r\n        mode: \"660\"\r\n      delegate_to: localhost\r\n      when: not exchange_iso_check.stat.exists\r\n\r\n- name: create EXCHANGE folder\r\n  ansible.windows.win_file:\r\n    path: \"{{ ludus_exchange_iso_directory }}\"\r\n    state: directory\r\n\r\n- name: Check if EXCHANGE 2016 ISO exists on host\r\n  ansible.windows.win_stat:\r\n    path: \"{{ ludus_exchange_iso_directory }}\\\\{{ ludus_exchange2016_iso_url.split('/') | last }}\"\r\n  register: exchange_iso_host_check\r\n\r\n- name: Copy Exchange ISO to windows host\r\n  ansible.windows.win_copy:\r\n    src: \"{{ ludus_install_directory }}/resources/iso/{{ ludus_exchange2016_iso_url.split('/') | last }}\"\r\n    dest: \"{{ ludus_exchange_iso_directory }}\\\\{{ ludus_exchange2016_iso_url.split('/') | last }}\"\r\n  when: not exchange_iso_host_check.stat.exists\r\n"
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/tasks/ludus-download-exchange-2019.yml",
    "content": "- name: Get Exchange ISO if needed\r\n  run_once: true\r\n  block:\r\n    - name: \"Create {{ ludus_install_directory }}/resources/iso directory if it doesn't exist\"\r\n      ansible.builtin.file:\r\n        path: \"{{ ludus_install_directory }}/resources/iso\"\r\n        state: directory\r\n        recurse: true\r\n      delegate_to: localhost\r\n\r\n    - name: Check if Exchange ISO exists\r\n      ansible.builtin.stat:\r\n        path: \"{{ ludus_install_directory }}/resources/iso/{{ ludus_exchange_iso_url.split('/') | last }}\"\r\n      delegate_to: localhost\r\n      register: exchange_iso_check\r\n\r\n    - name: Downloading EXCHANGE ISO - This will take a while\r\n      ansible.builtin.get_url:\r\n        url: \"{{ ludus_exchange_iso_url }}\"\r\n        dest: \"{{ ludus_install_directory }}/resources/iso/{{ ludus_exchange_iso_url.split('/') | last }}\"\r\n        mode: \"660\"\r\n      delegate_to: localhost\r\n      when: not exchange_iso_check.stat.exists\r\n\r\n- name: create EXCHANGE folder\r\n  ansible.windows.win_file:\r\n    path: \"{{ ludus_exchange_iso_directory }}\"\r\n    state: directory\r\n\r\n- name: Check if EXCHANGE ISO exists on host\r\n  ansible.windows.win_stat:\r\n    path: \"{{ ludus_exchange_iso_directory }}\\\\{{ ludus_exchange_iso_url.split('/') | last }}\"\r\n  register: exchange_iso_host_check\r\n\r\n- name: Copy Exchange ISO to windows host\r\n  ansible.windows.win_copy:\r\n    src: \"{{ ludus_install_directory }}/resources/iso/{{ ludus_exchange_iso_url.split('/') | last }}\"\r\n    dest: \"{{ ludus_exchange_iso_directory }}\\\\{{ ludus_exchange_iso_url.split('/') | last }}\"\r\n  when: not exchange_iso_host_check.stat.exists"
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/tasks/ludus-exchange-2016-install.yml",
    "content": "---\r\n- name: Mount Exchange 2016 ISO\r\n  community.windows.win_disk_image:\r\n    image_path: \"{{ ludus_exchange_iso_directory }}\\\\{{ ludus_exchange2016_iso_url.split('/') | last }}\"\r\n    state: present\r\n  register: iso_mount\r\n\r\n- name: Prepare Schema\r\n  ansible.windows.win_shell: |\r\n    & {{ iso_mount.mount_paths[0] }}Setup.exe /IAcceptExchangeServerLicenseTerms /PrepareSchema\r\n  vars:\r\n    ansible_become: true\r\n    ansible_become_method: runas\r\n    ansible_become_user: \"{{ ludus_exchange_domain_username }}\"\r\n    ansible_become_password: \"{{ ludus_exchange_domain_password }}\"\r\n\r\n- name: Prepare Active Directory\r\n  ansible.windows.win_shell: |\r\n    & {{ iso_mount.mount_paths[0] }}Setup.exe /IAcceptExchangeServerLicenseTerms /PrepareAD /OrganizationName:\"{{ ludus_exchange_domain }}\"\r\n  vars:\r\n    ansible_become: true\r\n    ansible_become_method: runas\r\n    ansible_become_user: \"{{ ludus_exchange_domain_username }}\"\r\n    ansible_become_password: \"{{ ludus_exchange_domain_password }}\"\r\n\r\n- name: Install Exchange 2016\r\n  ansible.windows.win_shell: |\r\n    & {{ iso_mount.mount_paths[0] }}Setup.exe /IAcceptExchangeServerLicenseTerms /Mode:Install /Role:Mailbox\r\n  vars:\r\n    ansible_become: true\r\n    ansible_become_method: runas\r\n    ansible_become_user: \"{{ ludus_exchange_domain_username }}\"\r\n    ansible_become_password: \"{{ ludus_exchange_domain_password }}\"\r\n\r\n- name: Unmount ISO\r\n  community.windows.win_disk_image:\r\n    image_path: \"{{ ludus_exchange_iso_directory }}\\\\{{ ludus_exchange2016_iso_url.split('/') | last }}\"\r\n    state: absent\r\n\r\n\r\n- name: Remove ISO file\r\n  ansible.windows.win_file:\r\n    path: \"{{ ludus_exchange_iso_directory }}\\\\{{ ludus_exchange2016_iso_url.split('/') | last }}\"\r\n    state: absent\r\n"
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/tasks/ludus-exchange-2019-install.yml",
    "content": "---\r\n- name: Mount Exchange ISO\r\n  community.windows.win_disk_image:\r\n    image_path: \"{{ ludus_exchange_iso_directory }}\\\\{{ ludus_exchange_iso_url.split('/') | last }}\"\r\n    state: present\r\n  register: iso_mount\r\n\r\n- name: Prepare Schema\r\n  ansible.windows.win_shell: |\r\n    & {{ iso_mount.mount_paths[0] }}Setup.exe /IAcceptExchangeServerLicenseTerms /PrepareSchema\r\n  vars:\r\n    ansible_become: true\r\n    ansible_become_method: runas\r\n    ansible_become_user: \"{{ ludus_exchange_domain_username }}\"\r\n    ansible_become_password: \"{{ ludus_exchange_domain_password }}\"\r\n\r\n- name: Prepare Active Directory\r\n  ansible.windows.win_shell: |\r\n    & {{ iso_mount.mount_paths[0] }}Setup.exe /IAcceptExchangeServerLicenseTerms /PrepareAD /OrganizationName:\"{{ ludus_exchange_domain }}\"\r\n  vars:\r\n    ansible_become: true\r\n    ansible_become_method: runas\r\n    ansible_become_user: \"{{ ludus_exchange_domain_username }}\"\r\n    ansible_become_password: \"{{ ludus_exchange_domain_password }}\"\r\n\r\n- name: Install Exchange\r\n  ansible.windows.win_shell: |\r\n    & {{ iso_mount.mount_paths[0] }}Setup.exe /IAcceptExchangeServerLicenseTerms /Mode:Install /Role:Mailbox\r\n  vars:\r\n    ansible_become: true\r\n    ansible_become_method: runas\r\n    ansible_become_user: \"{{ ludus_exchange_domain_username }}\"\r\n    ansible_become_password: \"{{ ludus_exchange_domain_password }}\"\r\n\r\n- name: Unmount ISO\r\n  community.windows.win_disk_image:\r\n    image_path: \"{{ ludus_exchange_iso_directory }}\\\\{{ ludus_exchange_iso_url.split('/') | last }}\"\r\n    state: absent\r\n\r\n- name: Remove ISO file\r\n  ansible.windows.win_file:\r\n    path: \"{{ ludus_exchange_iso_directory }}\\\\{{ ludus_exchange_iso_url.split('/') | last }}\"\r\n    state: absent\r\n"
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/tasks/ludus-exchange-dns.yml",
    "content": "---\n- name: Configure InternalDNSAdapter\n  ansible.windows.win_powershell:\n    script: |\n      [CmdletBinding()]\n        param (\n            [String]\n            $DomainAdapter\n        )\n      Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn\n      \n      $transport_service = Get-TransportService\n      \n      $adapterGUID = (Get-WmiObject Win32_NetworkAdapter | Where-Object { $_.NetConnectionID -eq $DomainAdapter }).GUID\n      $adapterGUID = $adapterGUID -replace '.*\\\\|\\{|\\}', ''\n      \n      if ( $transport_service.InternalDNSAdapterGuid -ne $null -And $adapterGUID -eq $transport_service.InternalDNSAdapterGuid.Guid ) {\n        $Ansible.Changed = $false\n      } else {\n        Set-TransportService $transport_service.name -ExternalDNSAdapterEnabled $false -ExternalDNSServers 1.1.1.1 -InternalDNSAdapterEnabled $true -InternalDNSAdapterGuid $adapterGUID\n        $Ansible.Changed = $true\n      }\n    parameters:\n      DomainAdapter: \"{{domain_adapter}}\"\n  vars:\n    ansible_become: true\n    ansible_become_method: runas\n    ansible_become_user: \"{{ ludus_exchange_domain_username }}\"\n    ansible_become_password: \"{{ ludus_exchange_domain_password }}\"\n  register: internal_dns_adapter\n  when: two_adapters  # Only execute if two_adapters are defined\n\n- name: Restart the Exchange Transport service\n  win_service:\n    name: MSExchangeTransport\n    state: restarted\n  when: two_adapters and internal_dns_adapter.changed\n"
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/tasks/ludus-exchange-pre.yml",
    "content": "---\r\n- name: Check if pre-req installation is completed\r\n  win_stat:\r\n    path: \"{{ exchange_prereqs_complete_file }}\"\r\n  register: prereq_check\r\n\r\n- block:\r\n    - name: Install IIS 6 Compatibility Features\r\n      win_feature:\r\n        name:\r\n          - Server-Media-Foundation\r\n          - NET-Framework-45-Features\r\n          - RPC-over-HTTP-proxy\r\n          - RSAT-Clustering\r\n          - RSAT-Clustering-CmdInterface\r\n          - RSAT-Clustering-Mgmt\r\n          - RSAT-Clustering-PowerShell\r\n          - WAS-Process-Model\r\n          - Web-Asp-Net45\r\n          - Web-Basic-Auth\r\n          - Web-Client-Auth\r\n          - Web-Digest-Auth\r\n          - Web-Dir-Browsing\r\n          - Web-Dyn-Compression\r\n          - Web-Http-Errors\r\n          - Web-Http-Logging\r\n          - Web-Http-Redirect\r\n          - Web-Http-Tracing\r\n          - Web-ISAPI-Ext\r\n          - Web-ISAPI-Filter\r\n          - Web-Lgcy-Mgmt-Console\r\n          - Web-Metabase\r\n          - Web-Mgmt-Console\r\n          - Web-Mgmt-Service\r\n          - Web-Net-Ext45\r\n          - Web-Request-Monitor\r\n          - Web-Server\r\n          - Web-Stat-Compression\r\n          - Web-Static-Content\r\n          - Web-Windows-Auth\r\n          - Web-WMI\r\n          - Windows-Identity-Foundation\r\n          - RSAT-ADDS\r\n          - ADLDS\r\n        state: present\r\n\r\n    - name: Enable Windows optional features\r\n      win_optional_feature:\r\n        name:\r\n          - IIS-IIS6ManagementCompatibility\r\n          - IIS-Metabase\r\n        state: present\r\n\r\n    - name: Install .NET Framework\r\n      win_package:\r\n        path: \"{{ exchange_dotnet_install_path }}\"\r\n        arguments: /q /norestart\r\n        state: present\r\n      register: dotnet_install\r\n\r\n    - name: Reboot after installing .NET Framework 4.8\r\n      win_reboot:\r\n      when: dotnet_install.rc == 3010  # 3010 means a reboot is required\r\n\r\n    - name: Wait for the machine to be up after reboot\r\n      wait_for_connection:\r\n        timeout: 300\r\n\r\n    - name: Install Visual C++ Redistributable for Visual Studio 2013\r\n      win_package:\r\n        path: \"{{ vcredist2013_install_path }}\"\r\n        arguments: /q /norestart\r\n        state: present\r\n      register: vcredist2013_install\r\n\r\n    - name: Reboot after installing Visual C++ Redistributable for Visual Studio 2013\r\n      win_reboot:\r\n      when: vcredist2013_install.changed\r\n\r\n    - name: The IIS URL Rewrite Module is required with Exchange Server 2016 CU22 and Exchange Server 2019 CU11 or later\r\n      win_package:\r\n        path: \"{{ rewrite_module_path }}\"\r\n        arguments: /q /norestart\r\n        state: present\r\n\r\n    - name: Install Unified Communications Managed API 4.0 Runtime.\r\n      win_package:\r\n        path: \"{{ ucma_runtime_path }}\"\r\n        arguments: /q /norestart\r\n        product_id: UCMA4\r\n        state: present\r\n      register: pri_exchange_ucma_install\r\n\r\n    - name: reboot after installing Unified Communications Managed API 4.0 Runtime\r\n      win_reboot:\r\n      when: pri_exchange_ucma_install.reboot_required\r\n\r\n    - name: Wait for the machine to be up after reboot\r\n      wait_for_connection:\r\n        timeout: 300\r\n\r\n    - name: Install Windows features ADLDS Exchange Transport Hub\r\n      win_feature:\r\n        name:\r\n          - ADLDS\r\n        state: present\r\n\r\n    - name: Create file marker for pre-req installation completion\r\n      win_shell: New-Item -Path \"{{ exchange_prereqs_complete_file }}\" -ItemType \"file\"\r\n      when: not prereq_check.stat.exists\r\n\r\n    - name: Reboot the system\r\n      win_reboot:\r\n        reboot_timeout: 300\r\n\r\n    - name: Wait for the machine to be up after reboot\r\n      wait_for_connection:\r\n        timeout: 300\r\n\r\n  when: not prereq_check.stat.exists\r\n\r\n- name: Check if pre-req installation is already completed\r\n  debug:\r\n    msg: \"Pre-req installation is already completed. Skipping Pre-req installation tasks.\"\r\n  when: prereq_check.stat.exists\r\n"
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/tasks/ludus_sendconnector.yml",
    "content": "---\n- name: Alert if send_connector_smtpserver is not set or empty\n  ansible.builtin.debug:\n    msg: >\n      \"send_connector_smtpserver is not set or is empty. Please make sure to set it in the role vars.\"\n  when: send_connector_smtpserver == \"\" or send_connector_smtpserver is not defined\n  \n- name: Configure Send Connector\n  ansible.windows.win_shell: |\n    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn\n    New-SendConnector -Name \"{{ send_connector_name }}\" -Custom -SmartHosts \"{{ send_connector_smtpserver }}\" -AddressSpaces (\"{{ send_connector_address_spaces | join(',') }}\") -SourceTransportServers \"{{ send_connector_source_transport_servers }}\"\n  vars:\n    ansible_become: true\n    ansible_become_method: runas\n    ansible_become_user: \"{{ ludus_exchange_domain_username }}\"\n    ansible_become_password: \"{{ ludus_exchange_domain_password }}\"\n  when: send_connector_name is defined  # Only execute if send_connector_name is defined \n"
  },
  {
    "path": "extensions/exchange/ansible/roles/ludus_exchange/tasks/main.yml",
    "content": "---\r\n- name: Check if Exchange is installed\r\n  win_service:\r\n    name: \"MSExchangeFrontendTransport\"\r\n  register: exchange_installed\r\n\r\n- name: Download Exchange ISO for Windows Server 2016\r\n  ansible.builtin.include_tasks: ludus-download-exchange-2016.yml\r\n  when: ludus_os_version == \"2016\" and not exchange_installed.exists\r\n\r\n- name: Download Exchange ISO for Windows Server 2019\r\n  ansible.builtin.include_tasks: ludus-download-exchange-2019.yml\r\n  when: ludus_os_version in [\"2019\", \"2022\"] and not exchange_installed.exists\r\n\r\n- name: Ludus Exchange Server features to be installed\r\n  ansible.builtin.include_tasks: ludus-exchange-pre.yml\r\n  when: not exchange_installed.exists\r\n\r\n- name: Install Exchange Server for Windows Server 2016\r\n  ansible.builtin.include_tasks: ludus-exchange-2016-install.yml\r\n  when: ludus_os_version == \"2016\" and not exchange_installed.exists\r\n\r\n- name: Install Exchange Server for Windows Server 2019\r\n  ansible.builtin.include_tasks: ludus-exchange-2019-install.yml\r\n  when: ludus_os_version in [\"2019\", \"2022\"] and not exchange_installed.exists\r\n\r\n- name: Create ad users mailbox\r\n  ansible.builtin.include_tasks: ludus-create-mailbox.yml\r\n\r\n- name: Setup internal dns adapter\r\n  ansible.builtin.include_tasks: ludus-exchange-dns.yml\r\n\r\n#- name: Run the send connector task\r\n#  ansible.builtin.include_tasks: ludus_sendconnector.yml\r\n#  when: exchange_installed.exists or send_connector_name is defined\r\n"
  },
  {
    "path": "extensions/exchange/data/config.json",
    "content": "{\n    \"lab_extension\": {\n        \"hosts\": {\n            \"srv01\": {\n                \"hostname\": \"the-eyrie\",\n                \"type\": \"server\",\n                \"local_admin_password\": \"FP.xh5Fk9Z1c\",\n                \"domain\": \"sevenkingdoms.local\",\n                \"path\": \"DC=sevenkingdoms,DC=local\",\n                \"local_groups\": {\n                    \"Administrators\": [\n                        \"sevenkingdoms\\\\lysa.arryn\"\n                    ],\n                    \"Remote Desktop Users\": [\n                        \"sevenkingdoms\\\\Arryn\"\n                    ]\n                }\n            }\n        },\n        \"domains\": {\n            \"sevenkingdoms.local\": {\n                \"organisation_units\": {},\n                \"groups\": {\n                    \"universal\": {},\n                    \"global\": {\n                        \"Arryn\": {\n                            \"managed_by\": \"lysa.arryn\",\n                            \"path\": \"OU=Vale,DC=sevenkingdoms,DC=local\"\n                        }\n                    },\n                    \"domainlocal\": {}\n                },\n                \"users\": {\n                    \"lysa.arryn\": {\n                        \"firstname\": \"Lysa\",\n                        \"surname\": \"Arryn\",\n                        \"password\": \"rob1nIsMyHeart\",\n                        \"city\": \"The Eyries\",\n                        \"description\": \"Lysa Arryn\",\n                        \"groups\": [\n                            \"Arryn\"\n                        ],\n                        \"path\": \"OU=Vale,DC=sevenkingdoms,DC=local\"\n                    },\n                    \"robin.arryn\": {\n                        \"firstname\": \"Robin\",\n                        \"surname\": \"Arryn\",\n                        \"password\": \"mommy\",\n                        \"city\": \"The Eyries\",\n                        \"description\": \"Robin Arryn\",\n                        \"groups\": [\n                            \"Arryn\"\n                        ],\n                        \"path\": \"OU=Vale,DC=sevenkingdoms,DC=local\"\n                    }\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "extensions/exchange/extension.json",
    "content": "{\n    \"name\": \"exchange\",\n    \"description\": \"Add an exchange to goad lab\",\n    \"machines\": [\n        \"srv01 (the-eyrie.sevenkingdoms.local)\"\n    ],\n    \"compatibility\": [\n        \"GOAD\",\n        \"GOAD-Light\",\n        \"GOAD-Mini\"\n    ],\n    \"impact\": \"Modify the ad schema and add a computer (warning the exchange machine is really heavy)\"\n}"
  },
  {
    "path": "extensions/exchange/inventory",
    "content": "[default]\n{% if provider_name == 'aws' or provider_name == 'azure' %}\nsrv01 ansible_host={{ip_range}}.21 dns_domain=dc01 dict_key=srv01 ansible_user=ansible ansible_password=FP.xh5Fk9Z1c\n{% else %}\nsrv01 ansible_host={{ip_range}}.21 dns_domain=dc01 dict_key=srv01\n{% endif %}\n\n[domain]\nsrv01\n\n[extensions]\nsrv01"
  },
  {
    "path": "extensions/exchange/providers/aws/windows.tf",
    "content": "\"srv01\" = {\n  name               = \"srv01\"\n  domain             = \"sevenkingdoms.local\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.xlarge\"   # t2.xlarge = 4cpu / 16GB\n  private_ip_address = \"{{ip_range}}.21\"\n  password           = \"FP.xh5Fk9Z1c\"\n}\n"
  },
  {
    "path": "extensions/exchange/providers/azure/windows.tf",
    "content": "\"srv01\" = {\n  name               = \"srv01\"\n  publisher          = \"MicrosoftWindowsServer\"\n  offer              = \"WindowsServer\"\n  windows_sku        = \"2019-Datacenter\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.21\"\n  password           = \"FP.xh5Fk9Z1c\"\n  size               = \"Standard_B4ms\" # Standard_B4ms : 4 cpu / 16 GB\n}"
  },
  {
    "path": "extensions/exchange/providers/ludus/config.yml",
    "content": "  - vm_name: \"{{ range_id }}-GOAD-SRV01\"\n    hostname: \"{{ range_id }}-SRV01\"\n    template: win2019-server-x64-template\n    vlan: 10\n    ip_last_octet: 21\n    ram_gb: 12\n    cpus: 4\n    windows:\n      sysprep: true"
  },
  {
    "path": "extensions/exchange/providers/proxmox/windows.tf",
    "content": "\"srv01\" = {\n  name               = \"SRV01\"\n  desc               = \"SRV01 - windows server 2019 - {{ip_range}}.10\"\n  cores              = 4\n  memory             = 12000\n  clone              = \"Ubuntu_2404_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.21/24\"\n  gateway            = \"{{ip_range}}.1\"\n}"
  },
  {
    "path": "extensions/exchange/providers/virtualbox/Vagrantfile",
    "content": "boxes.append(\n  { :name => \"{{lab_name}}-SRV01\",\n    :ip => \"{{ip_range}}.21\",\n    :box => \"StefanScherer/windows_2019\",\n    :os => \"windows\",\n    :cpus => 4,\n    :mem => 12000\n  }\n)"
  },
  {
    "path": "extensions/exchange/providers/vmware/Vagrantfile",
    "content": "boxes.append(\n  { :name => \"{{lab_name}}-SRV01\",\n    :ip => \"{{ip_range}}.21\",\n    :box => \"StefanScherer/windows_2019\",\n    :os => \"windows\",\n    :cpus => 4,\n    :mem => 12000\n  }\n)"
  },
  {
    "path": "extensions/guacamole/README.md",
    "content": "# guacamole extension\n\n- Extension Name: guacamole\n- Description: Add a guacamole\n- Machine name : guacamole\n- Compatible with labs : *\n\n## Install\n\n```\ninstance_id> install_extension guacamole\n```\n"
  },
  {
    "path": "extensions/guacamole/ansible/ansible.cfg",
    "content": "[defaults]\nhost_key_checking = false\ndisplay_skipped_hosts = false\nshow_per_host_start     = True\ndeprecation_warning   = false\n;stdout_callback         = yaml\n\n; add default roles folder into roles_path\nroles_path = ./roles:../../../ansible/roles:$HOME/.ansible/roles:/etc/ansible/roles"
  },
  {
    "path": "extensions/guacamole/ansible/install.yml",
    "content": "---\n- name: \"Read lab data files\"\n  hosts: guacamole\n  connection: local\n  vars_files:\n    - \"../../../ad/{{domain_name}}/data/config.json\"\n  tasks:\n    - name: register lab var\n      set_fact:\n        lab: \"{{lab}}\"\n        cacheable: yes\n      run_once: true\n\n# read all configuration file\n- name: \"Read local config file to add on lab config\"\n  hosts: guacamole\n  connection: local\n  tasks:\n    - name: Include and merge config file\n      vars:\n        ext_config: {}\n      ansible.builtin.include_vars:\n        file: \"../../{{ item }}/data/config.json\"\n        name: ext_config\n      loop:\n        - exchange\n        - lx01\n        - ws01\n      register: included_vars\n\n    - name: Debug included configs\n      debug:\n        var: item.ansible_facts.ext_config\n      loop: \"{{ included_vars.results }}\"\n\n    - name: Merge all included configs into lab\n      set_fact:\n        lab: \"{{ lab | combine(item.ansible_facts.ext_config.lab_extension, recursive=True) }}\"\n      loop: \"{{ included_vars.results }}\"\n\n    - name: Debug final merged lab variable\n      debug:\n        var: lab\n\n# --- install\n- name: Install Guacamole\n  hosts: guacamole\n  become: yes\n  vars_files:\n    - \"../../../guacamole.yml\"\n  roles:\n  - { role: 'geerlingguy.mysql', tags: 'mysql'}\n  - { role: 'linux/tomcat', tags: 'tomcat'}\n  - { role: 'linux/guacamole', tags: 'guacamole'}\n  vars:\n    mysql_databases:\n      - name: \"{{guacamole_db}}\"\n        encoding: utf8\n        collation: utf8_general_ci\n    mysql_users:\n      - name: \"{{guacamole_db_username}}\"\n        host: \"%\"\n        password: \"{{guacamole_db_password}}\"\n        priv: \"{{guacamole_db}}.*:ALL\"\n    salt: \"{{99999999999999 | random | to_uuid | hash('sha256')}}\"\n\n# --- create connections\n- name: Create guacamole connections\n  hosts: guacamole\n  become: yes\n  vars_files:\n    - \"../../../guacamole.yml\"\n  roles:\n  - { role: 'linux/guacamole_create_connections', tags: 'guacamole_connections'}\n  vars:\n    guacadmin_username: \"guacadmin\"\n    hosts: \"{{lab.hosts}}\"\n    domains: \"{{lab.domains}}\""
  },
  {
    "path": "extensions/guacamole/extension.json",
    "content": "{\n    \"name\": \"guacamole\",\n    \"description\": \"Add guacamole to quickly connect to lab\",\n    \"machines\": [\n        \"guacamole\"\n    ],\n    \"compatibility\": [\"*\"],\n    \"impact\": \"none\"\n}"
  },
  {
    "path": "extensions/guacamole/inventory",
    "content": "[default]\nguacamole ansible_host={{ip_range}}.52 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no'\n\n[extensions]\nguacamole\n"
  },
  {
    "path": "extensions/guacamole/providers/aws/linux.tf",
    "content": "\"guacamole\" = {\n  name               = \"guacamole\"\n  linux_sku          = \"22_04-lts-gen2\"\n  linux_version      = \"latest\"\n  ami                = \"ami-04c332520bd9cedb4\"\n  private_ip_address = \"{{ip_range}}.52\"\n  password           = \"sgHvnkThdsXlsd\"\n  size               = \"t2.medium\"  # 2cpu / 4GB\n}"
  },
  {
    "path": "extensions/guacamole/providers/azure/linux.tf",
    "content": "\"guacamole\" = {\n  name               = \"guacamole\"\n  linux_offer        = \"0001-com-ubuntu-server-jammy\"\n  linux_sku          = \"22_04-lts-gen2\"\n  linux_version      = \"latest\"\n  private_ip_address = \"{{ip_range}}.52\"\n  password           = \"sgHvnkThdsXlsd\"\n  size               = \"Standard_B2s\"  # 2cpu/4G\n}\n"
  },
  {
    "path": "extensions/guacamole/providers/ludus/config.yml",
    "content": "  - vm_name: \"{{ range_id }}-GUACAMOLE\"\n    hostname: \"{{ range_id }}-GUACAMOLE\"\n    template: ubuntu-22.04-x64-server-template\n    vlan: 10\n    ip_last_octet: 52\n    ram_gb: 4\n    cpus: 2\n    linux: true\n"
  },
  {
    "path": "extensions/guacamole/providers/proxmox/linux.tf",
    "content": "\"guacamole\" = {\n  name               = \"guacamole\"\n  desc               = \"guacamole GOAD\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"Ubuntu_2204_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.52/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n"
  },
  {
    "path": "extensions/guacamole/providers/virtualbox/Vagrantfile",
    "content": "boxes.append(\n    { :name => \"{{lab_name}}-GUACAMOLE\",\n      :ip => \"{{ip_range}}.52\",\n      :box => \"bento/ubuntu-22.04\", \n      :os => \"linux\",\n      :cpus => 2,\n      :mem => 3000,\n      :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n    }\n)"
  },
  {
    "path": "extensions/guacamole/providers/vmware/Vagrantfile",
    "content": "boxes.append(\n    { :name => \"{{lab_name}}-GUACAMOLE\",\n      :ip => \"{{ip_range}}.52\",\n      :box => \"bento/ubuntu-22.04\", \n      :os => \"linux\",\n      :cpus => 2,\n      :mem => 3000,\n      :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n    }\n)"
  },
  {
    "path": "extensions/lx01/ansible/ansible.cfg",
    "content": "[defaults]\nhost_key_checking = false\ndisplay_skipped_hosts = false\nshow_per_host_start     = True\ndeprecation_warning   = false\n;stdout_callback         = yaml\n\n; add default roles folder into roles_path\nroles_path = ./roles:../../../ansible/roles"
  },
  {
    "path": "extensions/lx01/ansible/install.yml",
    "content": "---\n# read global configuration file and set up adapters\n- import_playbook: \"../../../ansible/data.yml\"\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# read local configuration file\n- name: \"Read local config file\"\n  hosts: domain:extensions\n  connection: local\n  vars_files:\n    - \"../data/config.json\"\n  tasks:\n    - name: merge lab variable with local config\n      set_fact:\n        lab: \"{{ lab|combine(lab_extension, recursive=True) }}\"\n\n# provision ----\n- name: Enroll lx01 machine to domain\n  hosts: lx01\n  become: yes\n  roles:\n  - { role: 'linux/add_linux_to_domain', tags: 'linux_domain'}\n  vars:\n    hostname: \"{{lab.hosts[dict_key].hostname}}\"\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    dc_key: \"{{lab.domains[domain].dc}}\"\n    dc_name: \"{{lab.hosts[dc_key].hostname}}\"\n    dc_fqdn: \"{{dc_name}}.{{domain}}\"\n    dc_ip: \"{{hostvars[dc_key].ansible_host}}\"\n    domain_username: \"{{admin_user}}\"\n    domain_password: \"{{lab.domains[domain].domain_password}}\"\n    sudoers_group: \"{{lab.hosts[dict_key].local_groups.sudoers | default([])}}\"\n    ssh_group: \"{{lab.hosts[dict_key].local_groups.ssh | default([])}}\"\n\n- name: Setup lx01 machine dns on domain controler\n  hosts: dc01\n  roles:\n  - { role: 'add_dns_record', tags: 'add_dns_record'}\n  vars:\n    domain: \"{{lab.hosts[dict_key].domain}}\"\n    record_name: \"{{lab.hosts['lx01'].hostname}}\"\n    record_type: \"A\"\n    record_value:  \"{{hostvars['lx01'].ansible_host}}\"\n\n# - name: Setup lx01 machine as proxy\n#   hosts: lx01\n#   become: yes\n#   roles:\n#   - { role: 'linux/proxy_server', tags: 'linux_domain'}\n#   vars:\n#     hostname: \"{{lab.hosts[dict_key].hostname}}\"\n#     domain: \"{{lab.hosts[dict_key].domain}}\"\n#     squid_port: \"3128\"\n#     ip_range: \"{{hostvars[dict_key].ansible_host}}/24\"\n#     proxy_fqdn: \"{{hostname}}.{{domain}}\"\n# \n# - name: Setup lx01 machine as wpad CNAME in dns of domain controlers\n#   hosts: dc\n#   tasks:\n#     - name: reset dns query blocklist (to remove wpad from list)\n#       ansible.windows.win_shell:  dnscmd /config /globalqueryblocklist\n#   roles:\n#     - { role: 'add_dns_record', tags: 'add_dns_record'}\n#   vars:\n#     domain: \"{{lab.hosts[dict_key].domain}}\"\n#     record_name: \"wpad\"\n#     record_type: \"CNAME\"\n#     record_value: \"{{lab.hosts['lx01'].hostname}}.{{lab.hosts['lx01'].domain}}\"\n"
  },
  {
    "path": "extensions/lx01/data/config.json",
    "content": "{\n    \"lab_extension\" : {\n        \"hosts\" : {\n          \"lx01\" : {\n              \"hostname\" : \"dragonstone\", \n              \"type\" : \"server\",\n              \"os\": \"linux\",\n              \"local_admin_password\": \"HGLXP@ssw_rd$\",\n              \"domain\" : \"sevenkingdoms.local\", \n              \"path\" : \"DC=sevenkingdoms,DC=local\",\n              \"local_groups\" : {\n                  \"sudoers\" : [\"Baratheon\"],\n                  \"ssh\" : [\"Lannister\", \"Baratheon\"]\n              },\n              \"security\": [\"\"],\n              \"security_vars\": {}\n          }\n        }\n    }\n  }"
  },
  {
    "path": "extensions/lx01/extension.json",
    "content": "{\n    \"name\": \"lx01\",\n    \"description\": \"Add a linux computer enrolled to the lab\",\n    \"machines\": [\n        \"lx01\"\n    ],\n    \"compatibility\": [\n        \"GOAD\",\n        \"GOAD-Light\",\n        \"GOAD-Mini\"\n    ],\n    \"impact\": \"none\"\n}"
  },
  {
    "path": "extensions/lx01/inventory",
    "content": "[default]\nlx01 ansible_host={{ip_range}}.32  dict_key=lx01 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no'\n\n[extensions]\nlx01\n\n[linux_domain]\nlx01\n"
  },
  {
    "path": "extensions/lx01/providers/aws/linux.tf",
    "content": "\"lx01\" = {\n  name               = \"lx01\"\n  linux_sku          = \"22_04-lts-gen2\"\n  linux_version      = \"latest\"\n  ami                = \"ami-04c332520bd9cedb4\"\n  private_ip_address = \"{{ip_range}}.32\"\n  password           = \"HGLXP@ssw_rd$\"\n  instance_type      = \"t2.micro\"  # 1cpu / 1GB\n}"
  },
  {
    "path": "extensions/lx01/providers/azure/linux.tf",
    "content": "\"lx01\" = {\n  name               = \"lx01\"\n  linux_offer        = \"0001-com-ubuntu-server-jammy\"\n  linux_sku          = \"22_04-lts-gen2\"\n  linux_version      = \"latest\"\n  private_ip_address = \"{{ip_range}}.32\"\n  password           = \"HGLXP@ssw_rd$\"\n  size               = \"Standard_B1s\"  # 1cpu/1G\n}\n"
  },
  {
    "path": "extensions/lx01/providers/ludus/config.yml",
    "content": "  - vm_name: \"{{ range_id }}-LX01\"\n    hostname: \"{{ range_id }}-LX01\"\n    template: ubuntu-22.04-x64-server-template\n    vlan: 10\n    ip_last_octet: 32\n    ram_gb: 1\n    cpus: 1\n    linux: true\n"
  },
  {
    "path": "extensions/lx01/providers/proxmox/linux.tf",
    "content": "\"lx01\" = {\n  name               = \"lx01\"\n  desc               = \"lx01 GOAD\"\n  cores              = 1\n  memory             = 1024\n  clone              = \"Ubuntu_2204_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.32/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n"
  },
  {
    "path": "extensions/lx01/providers/virtualbox/Vagrantfile",
    "content": "boxes.append(\n    { :name => \"{{lab_name}}-LX01\",\n      :ip => \"{{ip_range}}.32\",\n      :box => \"bento/ubuntu-22.04\", \n      :os => \"linux\",\n      :cpus => 1,\n      :mem => 1000,\n      :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n    }\n)"
  },
  {
    "path": "extensions/lx01/providers/vmware/Vagrantfile",
    "content": "boxes.append(\n    { :name => \"{{lab_name}}-LX01\",\n      :ip => \"{{ip_range}}.32\",\n      :box => \"bento/ubuntu-22.04\", \n      :os => \"linux\",\n      :cpus => 1,\n      :mem => 1000,\n      :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n    }\n)"
  },
  {
    "path": "extensions/wazuh/README.md",
    "content": "# WAZUH extension\n\n- Extension Name: wazuh\n- Description: Add wazuh free EDR server and agent on all the domain computers + soc fortress rules (https://github.com/socfortress/Wazuh-Rules)\n- Machine name : {{lab_name}}-WAZUH\n- Compatible with labs : *\n\n## prerequisites\n\nOn ludus prepare template :\n```\nludus templates add -d ubuntu-22.04-x64-server\nludus templates build\n```\n\n## Install\n```\ninstance_id> install_extension wazuh\n```\n\n\n## credits\n- https://github.com/aleemladha (https://github.com/Orange-Cyberdefense/GOAD/pull/215)"
  },
  {
    "path": "extensions/wazuh/ansible/install.yml",
    "content": "#Aleem Ladha @LadhaAleem\n#Credits to SOCFortress and Mayfly277\n- name: Install and configure Wazuh Manager\n  hosts: wazuh_server\n  become: yes\n  roles:\n    - { role: 'wazuh_manager', tags: 'wazuh_manager' }\n\n- name: Install Wazuh Agent\n  hosts: wazuh_agents\n  roles:\n    - { role: 'wazuh_agent', tags: 'wazuh_agent' }\n  vars:\n    wazuh_manager_host: \"{{ hostvars['wazuh']['ansible_host'] }}\"\n\n- name: Install Wazuh Agent\n  hosts: wazuh_agents_linux\n  become: yes\n  roles:\n    - { role: 'wazuh_agent_linux', tags: 'wazuh_agent_linux' }\n  vars:\n    wazuh_manager_host: \"{{ hostvars['wazuh']['ansible_host'] }}\""
  },
  {
    "path": "extensions/wazuh/ansible/roles/wazuh_agent/defaults/main.yml",
    "content": "# Wazuh agent installation script URL\nwazuh_agent_install_package: \"https://packages.wazuh.com/4.x/windows/wazuh-agent-4.8.2-1.msi\"\n\nwazuh_install_location: \"c:\\\\tmp\"\n"
  },
  {
    "path": "extensions/wazuh/ansible/roles/wazuh_agent/tasks/main.yml",
    "content": "- name: Check if Wazuh Agent service is installed\n  win_service:\n    name: WazuhSvc\n  register: wazuh_agent_service\n\n- name: Create wazuh_install_location folder if not exist\n  ansible.windows.win_file:\n    path: \"{{wazuh_install_location}}\"\n    state: directory\n\n- name: Download Wazuh Agent MSI package\n  win_get_url:\n    url: \"{{ wazuh_agent_install_package }}\"\n    dest: \"{{wazuh_install_location}}/wazuh-agent\"\n  register: wazuh_agent_download\n  until: wazuh_agent_download is succeeded\n  when: not wazuh_agent_service.exists\n\n- name: Install Wazuh Agent\n  win_command: msiexec.exe /i \"{{wazuh_install_location}}\\wazuh-agent\" /q WAZUH_MANAGER={{ wazuh_manager_host }} WAZUH_REGISTRATION_SERVER={{ wazuh_manager_host }}\n  when: wazuh_agent_download is succeeded and not wazuh_agent_service.exists\n\n- name: Start Wazuh Agent service\n  win_service:\n    name: WazuhSvc\n    state: started\n    start_mode: auto\n  when: wazuh_agent_download is succeeded and not wazuh_agent_service.exists\n"
  },
  {
    "path": "extensions/wazuh/ansible/roles/wazuh_agent_linux/defaults/main.yml",
    "content": "wazuh_version: \"4.8.2-1\""
  },
  {
    "path": "extensions/wazuh/ansible/roles/wazuh_agent_linux/tasks/main.yml",
    "content": "- name: Gather service facts\n  ansible.builtin.service_facts:\n\n- name: \"Update cache\"\n  ansible.builtin.apt:\n    update_cache: true\n    cache_valid_time: 86400\n  when: \"'wazuh-agent.service' not in ansible_facts.services or ansible_facts.services['wazuh-agent.service'].state != 'running'\"\n\n- name: Add required dependencies.\n  ansible.builtin.apt:\n    name:\n      - apt-transport-https\n      - gnupg2\n    state: present\n  when: \"'wazuh-agent.service' not in ansible_facts.services or ansible_facts.services['wazuh-agent.service'].state != 'running'\"\n\n- name: Install wazuh apt key\n  ansible.builtin.apt_key:\n    url: https://packages.wazuh.com/key/GPG-KEY-WAZUH\n    state: present\n  when: \"'wazuh-agent.service' not in ansible_facts.services or ansible_facts.services['wazuh-agent.service'].state != 'running'\"\n\n- name: Add Wazuh repository.\n  ansible.builtin.apt_repository:\n    repo: 'deb https://packages.wazuh.com/4.x/apt/ stable main'\n    state: present\n    update_cache: true\n  when: \"'wazuh-agent.service' not in ansible_facts.services or ansible_facts.services['wazuh-agent.service'].state != 'running'\"\n\n- name: Install wazuh agent\n  ansible.builtin.apt: \n    name: \"wazuh-agent={{wazuh_version}}\"\n    state: present\n  environment:\n    WAZUH_MANAGER: \"{{wazuh_manager_host}}\"\n    WAZUH_REGISTRATION_SERVER: \"{{ wazuh_manager_host }}\"\n  when: \"'wazuh-agent.service' not in ansible_facts.services or ansible_facts.services['wazuh-agent.service'].state != 'running'\"\n\n- name: Start and enable wazuh-agent\n  ansible.builtin.service:\n    name: wazuh-agent\n    state: started\n    enabled: yes\n  when: \"'wazuh-agent.service' not in ansible_facts.services or ansible_facts.services['wazuh-agent.service'].state != 'running'\""
  },
  {
    "path": "extensions/wazuh/ansible/roles/wazuh_manager/defaults/main.yml",
    "content": "# Wazuh installation script URL\nwazuh_install_script_url: \"https://packages.wazuh.com/4.8/wazuh-install.sh\"\n\n# SOCFORTRESS Wazuh rules script URL\nsocfortress_rules_script_url: \"https://raw.githubusercontent.com/socfortress/Wazuh-Rules/main/wazuh_socfortress_rules.sh\"\n"
  },
  {
    "path": "extensions/wazuh/ansible/roles/wazuh_manager/files/wazuh_socfortress_rules.sh",
    "content": "#!/bin/bash\n# Credit to SOC Fortress for this amazing pack\n# credits : https://github.com/socfortress/Wazuh-Rules/blob/main/wazuh_socfortress_rules.sh\nPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\n\nclear\n\n## Continue?\n\n## Check if system is based on yum or apt-get\nif [ -n \"$(command -v yum)\" ]; then\n    sys_type=\"yum\"\n    sep=\"-\"\nelif [ -n \"$(command -v zypper)\" ]; then\n    sys_type=\"zypper\"   \n    sep=\"-\"  \nelif [ -n \"$(command -v apt-get)\" ]; then\n    sys_type=\"apt-get\"   \n    sep=\"=\"\nfi\n\n## Prints information\nlogger() {\n    now=$(date +'%m/%d/%Y %H:%M:%S')\n    case $1 in \n        \"-e\")\n            mtype=\"INFO:\"\n            message=\"$2\"\n            ;;\n        \"-w\")\n            mtype=\"WARNING:\"\n            message=\"$2\"\n            ;;\n        *)\n            mtype=\"INFO:\"\n            message=\"$1\"\n            ;;\n    esac\n    echo \"$now $mtype $message\"\n}\n\n\n## Check if Git exists\nif ! command -v git &> /dev/null\nthen\n    logger -e \"git package could not be found. Please install with yum/apt-get install git.\"\n    exit\nelse \n    logger -e \"git package found. Continuing...\"\nfi\n\n\ncheckArch() {\n    arch=$(uname -m)\n\n    if [ \"$arch\" != \"x86_64\" ]; then\n        logger -e \"Incompatible system. This script must be run on a 64-bit system.\"\n        exit 1\n    fi\n}\n\nrestartService() {\n    if [ -n \"$(ps -e | egrep '^\\s*1\\s.*systemd$')\" ]; then\n        eval \"systemctl restart $1.service ${debug}\"\n        if [ \"$?\" != 0 ]; then\n            logger -e \"${1^} could not be restarted. Please check /var/ossec/logs/ossec.log for details.\"\n            logger -e \"An error has occurred. Attempting to restore backed up rules\" \n            \\cp -r /tmp/wazuh_rules_backup/* /var/ossec/etc/rules/\n            chown wazuh:wazuh /var/ossec/etc/rules/*\n            chmod 660 /var/ossec/etc/rules/*\n            systemctl restart wazuh-manager\n            rm -rf /tmp/Wazuh-Rules\n        else\n            sleep 1\n        fi  \n    elif [ -n \"$(ps -e | egrep '^\\s*1\\s.*init$')\" ]; then\n        eval \"chkconfig $1 on ${debug}\"\n        eval \"service $1 restart ${debug}\"\n        eval \"/etc/init.d/$1 start ${debug}\"\n        if [ \"$?\" != 0 ]; then\n            logger -e \"${1^} could not be restarted. Please check /var/ossec/logs/ossec.log for details.\"\n            logger -e \"An error has occurred. Attempting to restore backed up rules\" \n            \\cp -r /tmp/wazuh_rules_backup/* /var/ossec/etc/rules/\n            chown wazuh:wazuh /var/ossec/etc/rules/*\n            chmod 660 /var/ossec/etc/rules/*\n            systemctl restart wazuh-manager\n            rm -rf /tmp/Wazuh-Rules\n        else\n            sleep 1\n        fi     \n    elif [ -x \"/etc/rc.d/init.d/$1\" ]; then\n        eval \"/etc/rc.d/init.d/$1 start ${debug}\"\n        if [ \"$?\" != 0 ]; then\n            logger -e \"${1^} could not be restarted. Please check /var/ossec/logs/ossec.log for details.\"\n        else\n            logger \"${1^} restarted\"\n        fi             \n    else\n        logger -e \"${1^} could not restart. No service found on the system.\"\n    fi\n}\n\nhealthCheck() {\n    cd /var/ossec || exit 1  # Set the current working directory to /var/ossec\n    logger \"Performing a health check\"\n    eval \"service wazuh-manager restart ${debug}\"\n    sleep 20\n    if [ -n \"$(/var/ossec/bin/wazuh-control status | grep 'wazuh-logcollector not running...')\" ]; then\n        logger -e \"Wazuh-Manager Service is not healthy. Please check /var/ossec/logs/ossec.log for details.\"\n    else\n        logger -e \"Wazuh-Manager Service is healthy. Thanks for checking us out :) Get started with our free-for-life tier here: https://www.socfortress.co/trial.html Happy Defending!\"\n        rm -rf /tmp/Wazuh-Rules\n    fi\n}\n\n## Install the required packages for the installation\ncloneRules() {\n    logger \"Beginning the Install\"\n\n    if [ \"$sys_type\" == \"yum\" ]; then\n        logger -e \"Verifying that Wazuh-Manager software is installed... continued\"\n        if rpm -qa | grep -q wazuh-manager; then\n            mkdir /tmp/wazuh_rules_backup\n            logger -e \"Backing up current rules into /tmp/wazuh_rules_backup/\"\n            \\cp -r /var/ossec/etc/rules/* /tmp/wazuh_rules_backup/\n            git clone https://github.com/socfortress/Wazuh-Rules.git /tmp/Wazuh-Rules\n            cd /tmp/Wazuh-Rules || exit 1\n            find . -name '*xml' -exec mv {} /var/ossec/etc/rules/ \\;\n            find /var/ossec/etc/rules/ -name 'decoder-linux-sysmon.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            find /var/ossec/etc/rules/ -name 'yara_decoders.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            find /var/ossec/etc/rules/ -name 'auditd_decoders.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            find /var/ossec/etc/rules/ -name 'naxsi-opnsense_decoders.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            find /var/ossec/etc/rules/ -name 'maltrail_decoders.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            find /var/ossec/etc/rules/ -name 'decoder-manager-logs.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            /var/ossec/bin/wazuh-control info 2>&1 | tee /tmp/version.txt\n            chown wazuh:wazuh /var/ossec/etc/rules/*\n            chmod 660 /var/ossec/etc/rules/*\n            systemctl restart wazuh-manager\n            cd /var/ossec || exit 1\n            rm -rf /tmp/Wazuh-Rules\n        else \n            logger -e \"Wazuh-Manager software could not be found or is not installed\"\n        fi\n    elif [ \"$sys_type\" == \"apt-get\" ]; then\n        logger -e \"Verifying that Wazuh-Manager software is installed... continued\"\n        if apt list --installed | grep -q wazuh-manager; then\n            mkdir /tmp/wazuh_rules_backup\n            logger -e \"Backing up current rules into /tmp/wazuh_rules_backup/\"\n            \\cp -r /var/ossec/etc/rules/* /tmp/wazuh_rules_backup/\n            git clone https://github.com/socfortress/Wazuh-Rules.git /tmp/Wazuh-Rules\n            cd /tmp/Wazuh-Rules || exit 1\n            find . -name '*xml' -exec mv {} /var/ossec/etc/rules/ \\;\n            find /var/ossec/etc/rules/ -name 'decoder-linux-sysmon.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            find /var/ossec/etc/rules/ -name 'yara_decoders.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            find /var/ossec/etc/rules/ -name 'auditd_decoders.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            find /var/ossec/etc/rules/ -name 'naxsi-opnsense_decoders.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            find /var/ossec/etc/rules/ -name 'maltrail_decoders.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            find /var/ossec/etc/rules/ -name 'decoder-manager-logs.xml' -exec mv {} /var/ossec/etc/decoders/ \\;\n            /var/ossec/bin/wazuh-control info 2>&1 | tee /tmp/version.txt\n            chown wazuh:wazuh /var/ossec/etc/rules/*\n            chmod 660 /var/ossec/etc/rules/*\n            systemctl restart wazuh-manager\n            cd /var/ossec || exit 1\n            rm -rf /tmp/Wazuh-Rules\n        else \n            logger -e \"Wazuh-Manager software could not be found or is not installed\"\n        fi\n    else\n        logger \"Continuing\"\n    fi\n\n    if [ \"$?\" != 0 ]; then\n        logger -e \"An error has occurred. Attempting to restore backed up rules\" \n        \\cp -r /tmp/wazuh_rules_backup/* /var/ossec/etc/rules/\n        chown wazuh:wazuh /var/ossec/etc/rules/*\n        chmod 660 /var/ossec/etc/rules/*\n        systemctl restart wazuh-manager\n        cd /var/ossec || exit 1\n        rm -rf /tmp/Wazuh-Rules\n    else\n        logger -e \"Rules downloaded, attempting to restart the Wazuh-Manager service\" \n        restartService \"wazuh-manager\"\n        sleep 5\n    fi     \n}\n\nmain() {\n    if [ \"$EUID\" -ne 0 ]; then\n        logger -e \"This script must be run as root.\"\n        exit 1\n    fi   \n\n    checkArch\n    cloneRules\n    healthCheck\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "extensions/wazuh/ansible/roles/wazuh_manager/tasks/main.yml",
    "content": "# use /opt/wazuh instead of /tmp to keep track\n- name: Create /opt/wazuh directory if it does not exist\n  ansible.builtin.file:\n    path: /opt/wazuh\n    state: directory\n    mode: '0755'\n\n# check existence to not reinstall if already installed\n- name: Check services facts\n  ansible.builtin.service_facts:\n\n# - name: Print service facts\n#   ansible.builtin.debug:\n#     var: ansible_facts.services\n\n- name: Download Wazuh installation script\n  get_url:\n    url: \"{{ wazuh_install_script_url }}\"\n    dest: /opt/wazuh/wazuh-install.sh\n  when: not ansible_facts.services['wazuh-manager.service'] is defined\n\n- name: Run Wazuh installation script\n  shell: sudo bash /opt/wazuh/wazuh-install.sh -a -i > /opt/wazuh/wazuh-install-output.txt\n  when: not ansible_facts.services['wazuh-manager.service'] is defined\n\n# FIX false positive on  /bin/diff  cf. https://github.com/wazuh/wazuh/issues/19000\n- name: fix rootkit trojan detection due to issue\n  ansible.builtin.lineinfile:\n    path: /var/ossec/etc/rootcheck/rootkit_trojans.txt\n    search_string: 'diff        !bash|^/bin/sh|file\\.h|proc\\.h|/dev/[^n]|^/bin/.*sh!'\n    line: 'diff        !bash|^/bin/sh|file\\.h|proc\\.h|/dev/[^nf]|^/bin/.*sh!'\n\n- name: Start Wazuh Manager service\n  service:\n    name: wazuh-manager\n    state: started\n    enabled: yes\n\n# check socfotress folder to avoid reinstall if already installed\n- name: Get stats of ossec directory\n  ansible.builtin.stat:\n    path: /var/ossec\n  register: ossec_folder\n\n- name: Download SOCFORTRESS Wazuh rules script\n  copy:\n    src: wazuh_socfortress_rules.sh\n    dest: /opt/wazuh/wazuh_socfortress_rules.sh\n    mode: \"0755\"  # Ensure the script is executable\n  when: not ossec_folder.stat.exists\n\n- name: Run SOCFORTRESS Wazuh rules script\n  shell: sudo bash /opt/wazuh/wazuh_socfortress_rules.sh\n  when: not ossec_folder.stat.exists\n\n- name: Extract username and password\n  shell: \"grep -E 'User:|Password:' /opt/wazuh/wazuh-install-output.txt | awk '{print $NF}'\"\n  register: access_info\n\n- name: Display username and password\n  debug:\n    msg:\n      - \"Username: {{ access_info.stdout_lines[0] }}\"\n      - \"Password: {{ access_info.stdout_lines[1] }}\"\n"
  },
  {
    "path": "extensions/wazuh/extension.json",
    "content": "{\n    \"name\": \"wazuh\",\n    \"description\": \"Add the wazuh EDR into the lab\",\n    \"machines\": [\n        \"wazuh\"\n    ],\n    \"compatibility\": [\n        \"*\"\n    ],\n    \"impact\": \"add a wazuh machine and a wazuh agent on all windows machine\"\n}"
  },
  {
    "path": "extensions/wazuh/inventory",
    "content": "[default]\nwazuh ansible_host={{ip_range}}.51 ansible_connection=ssh ansible_ssh_common_args='-o StrictHostKeyChecking=no'\n\n[extensions]\nwazuh\n\n; Recipe associations -------------------\n[wazuh_server]\nwazuh\n\n[wazuh_agents:children]\ndomain\n\n[wazuh_agents_linux:children]\nlinux_domain"
  },
  {
    "path": "extensions/wazuh/providers/aws/linux.tf",
    "content": "\"wazuh\" = {\n  name               = \"wazuh\"\n  linux_sku          = \"22_04-lts-gen2\"\n  linux_version      = \"latest\"\n  ami                = \"ami-04c332520bd9cedb4\"\n  private_ip_address = \"{{ip_range}}.51\"\n  password           = \"sgdvnkjhdshlsd\"\n  size               = \"t2.large\"  # 2cpu / 8GB\n}"
  },
  {
    "path": "extensions/wazuh/providers/azure/linux.tf",
    "content": "\"wazuh\" = {\n  name               = \"wazuh\"\n  linux_offer        = \"0001-com-ubuntu-server-jammy\"\n  linux_sku          = \"22_04-lts-gen2\"\n  linux_version      = \"latest\"\n  private_ip_address = \"{{ip_range}}.51\"\n  password           = \"sgdvnkjhdshlsd\"\n  size               = \"Standard_B2ms\"  # 2cpu/8G\n}\n"
  },
  {
    "path": "extensions/wazuh/providers/ludus/config.yml",
    "content": "  - vm_name: \"{{ range_id }}-WAZUH\"\n    hostname: \"{{ range_id }}-WAZUH\"\n    template: ubuntu-22.04-x64-server-template\n    vlan: 10\n    ip_last_octet: 51\n    ram_gb: 8\n    cpus: 2\n    linux: true\n"
  },
  {
    "path": "extensions/wazuh/providers/virtualbox/Vagrantfile",
    "content": "boxes.append(\n    { :name => \"{{lab_name}}-WAZUH\",\n      :ip => \"{{ip_range}}.51\",\n      :box => \"bento/ubuntu-22.04\", \n      :os => \"linux\",\n      :cpus => 2,\n      :mem => 8000,\n      :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n    }\n)"
  },
  {
    "path": "extensions/wazuh/providers/vmware/Vagrantfile",
    "content": "boxes.append(\n    { :name => \"{{lab_name}}-WAZUH\",\n      :ip => \"{{ip_range}}.51\",\n      :box => \"bento/ubuntu-22.04\", \n      :os => \"linux\",\n      :cpus => 2,\n      :mem => 8000,\n      :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n    }\n)"
  },
  {
    "path": "extensions/ws01/README.md",
    "content": "# WS01 extension (Workstation 01)\n\n- Extension Name: ws01\n- Description: Add a Windows 10 workstation to the lab GOAD or GOAD Light in the domain sevenkingdoms.local\n- Machine name : {{lab_name}}-WS01\n- Compatible with labs :\n  - GOAD\n  - GOAD-Light\n\n- Lab infos:\n  - hostname: casterlyrock \n  - Users:\n    - Administrators :\n      - tywin.lannister\n      - jaime.lannister\n    - RDP Users:\n      - Lannister group\n\n- Features :\n  - run_as_ppl\n  - powershell restricted\n  - asr rules :\n    - block lsass stealing\n    - block PSExec and WMI\n\n- Providers:\n  - aws doesn't provide windows10 ami. you can still install ws01 but a windows server 2019 will be used instead\n\n## prerequisites\n\nOn ludus prepare template :\n```\nludus templates add -d win10-21h1-x64-enterprise\nludus templates build\n```\n\n## Install\n\n```\ninstance_id> install_extension ws01\n```\n\n## Uninstall\n\n- Not implemented yet\n\n## credits:\n- asr rules implementation : https://github.com/zuesdevil (https://github.com/Orange-Cyberdefense/GOAD/pull/172)\n"
  },
  {
    "path": "extensions/ws01/ansible/ansible.cfg",
    "content": "[defaults]\nhost_key_checking = false\ndisplay_skipped_hosts = false\nshow_per_host_start     = True\ndeprecation_warning   = false\n;stdout_callback         = yaml\n\n; add default roles folder into roles_path\nroles_path = ./roles:../../../ansible/roles"
  },
  {
    "path": "extensions/ws01/ansible/install.yml",
    "content": "---\n# read global configuration file and set up adapters\n- import_playbook: \"../../../ansible/data.yml\"\n  vars:\n    data_path: \"../ad/{{domain_name}}/data/\"\n  tags: 'data'\n\n# read local configuration file\n- name: \"Read local config file\"\n  hosts: domain:extensions\n  connection: local\n  vars_files:\n    - \"../data/config.json\"\n  tasks:\n    - name: merge lab variable with local config\n      set_fact:\n        lab: \"{{ lab|combine(lab_extension, recursive=True) }}\"\n\n- name: \"Set execution policy unrestricted (in cas of re-run)\"\n  hosts: ws01\n  tasks:\n    - name: \"Change execution policy before running\"\n      win_shell: |\n        Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force\n\n- name: prepare workstation\n  hosts: ws01\n  roles:\n    # build.yml\n    - { role: 'common', tags: 'common', http_proxy: \"{{enable_http_proxy}}\" }\n    - { role: 'settings/keyboard', tags: 'keyboard', layouts: \"{{keyboard_layouts}}\" }\n    # ad-servers.yml\n    - { role: 'settings/admin_password', tags: 'admin_password' }\n    - { role: 'settings/hostname', tags: 'hostname' }\n    # ad-members.yml : enroll ws01\n    - { role: 'commonwkstn', tags: 'workstation' }\n    # ad-relations.yml : domain group and users local permissions\n    - { role: \"settings/adjust_rights\", tags: 'adjust_rights' }\n    - { role: \"settings/user_rights\", tags: 'adjust_rights' }\n  vars:\n    local_admin_password: \"{{lab.hosts[dict_key].local_admin_password}}\"\n    hostname: \"{{lab.hosts[dict_key].hostname}}\"\n    member_domain: \"{{lab.hosts[dict_key].domain}}\"\n    domain_username: \"{{member_domain}}\\\\{{admin_user}}\"\n    domain_password: \"{{lab.domains[member_domain].domain_password}}\"\n    local_groups: \"{{lab.hosts[dict_key].local_groups  | default({}) }}\"\n\n- name: \"Setup security with tasks\"\n  hosts: ws01\n  tasks:\n    - include_role:\n        name: \"security/{{secu}}\"\n      vars:\n        security_vars : \"{{ lab.hosts[dict_key].security_vars[secu] | default({}) }}\"\n        domain: \"{{lab.hosts[dict_key].domain}}\"\n        domain_username: \"{{member_domain}}\\\\{{admin_user}}\"\n        domain_password: \"{{lab.domains[member_domain].domain_password}}\"\n      loop: \"{{lab.hosts[dict_key].security | default([]) }}\"\n      loop_control:\n        loop_var: secu\n"
  },
  {
    "path": "extensions/ws01/data/config.json",
    "content": "{\n  \"lab_extension\" : {\n      \"hosts\" : {\n          \"ws01\" : {\n              \"hostname\" : \"casterlyrock\",\n              \"type\" : \"workstation\",\n              \"local_admin_password\": \"EP+xh7Rk6j90\",\n              \"domain\" : \"sevenkingdoms.local\",\n              \"path\" : \"DC=sevenkingdoms,DC=local\",\n              \"local_groups\" : {\n                  \"Administrators\" : [\n                      \"sevenkingdoms\\\\tywin.lannister\",\n                      \"sevenkingdoms\\\\jaime.lannister\"\n                  ],\n                  \"Remote Desktop Users\" : [\n                      \"sevenkingdoms\\\\Lannister\"\n                  ]\n              },\n              \"security\": [\"enable_run_as_ppl\", \"asr\", \"powershell_restrict\"],\n              \"security_vars\": {\n                  \"asr\" : { \"block lsass stealing\": {\"ruleid\" : \"9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2\"},\n                            \"block PSExec and WMI\": {\"ruleid\" : \"d1e49aac-8f56-4280-b9ba-993a6d77406c\"}}\n              }\n          }\n      }\n  }\n}"
  },
  {
    "path": "extensions/ws01/extension.json",
    "content": "{\n    \"name\": \"ws01\",\n    \"description\": \"Add an hardened workstation into the lab\",\n    \"machines\": [\n        \"ws01 (casterlyrock.sevenkingdoms.local)\"\n    ],\n    \"compatibility\": [\n        \"GOAD\",\n        \"GOAD-Light\",\n        \"GOAD-Mini\"\n    ],\n    \"impact\": \"aws doesn't provide windows10 ami. you can still install ws01 with aws but a windows server 2019 will be used instead\"\n}"
  },
  {
    "path": "extensions/ws01/inventory",
    "content": "[default]\n{% if provider_name == 'aws' or provider_name == 'azure' %}\nws01 ansible_host={{ip_range}}.31 dns_domain=dc01 dict_key=ws01 ansible_user=ansible ansible_password=EP+xh7Rk6j90\n{% else %}\nws01 ansible_host={{ip_range}}.31 dns_domain=dc01 dict_key=ws01\n{% endif %}\n\n[domain]\nws01\n\n[extensions]\nws01"
  },
  {
    "path": "extensions/ws01/providers/aws/windows.tf",
    "content": "# AWS only provide windows server AMI :/\n\"ws01\" = {\n  name               = \"ws01\"\n  domain             = \"sevenkingdoms.local\"\n  windows_sku        = \"2019-Datacenter\"\n  ami                = \"ami-03440f0d88fea1060\"\n  instance_type      = \"t2.medium\"\n  private_ip_address = \"{{ip_range}}.31\"\n  password           = \"EP+xh7Rk6j90\"\n}"
  },
  {
    "path": "extensions/ws01/providers/azure/windows.tf",
    "content": "\"ws01\" = {\n  name               = \"ws01\"\n  publisher          = \"MicrosoftWindowsDesktop\"\n  offer              = \"office-365\"\n  windows_sku        = \"win10-22h2-avd-m365\"\n  windows_version    = \"latest\"\n  private_ip_address = \"{{ip_range}}.31\"\n  password           = \"EP+xh7Rk6j90\"\n  size               = \"Standard_B2s\"\n}"
  },
  {
    "path": "extensions/ws01/providers/ludus/config.yml",
    "content": "  - vm_name: \"{{ range_id }}-GOAD-WS01\"\n    hostname: \"{{ range_id }}-WS01\"\n    template: win10-22h2-x64-enterprise-template\n    vlan: 10\n    ip_last_octet: 31\n    ram_gb: 4\n    cpus: 2\n    windows:\n      sysprep: true\n"
  },
  {
    "path": "extensions/ws01/providers/proxmox/windows.tf",
    "content": "\"ws01\" = {\n  name               = \"WS01\"\n  desc               = \"WS01 - windows 10 - {{ip_range}}.31\"\n  cores              = 2\n  memory             = 4096\n  clone              = \"Windows10_22h2_x64\"\n  dns                = \"{{ip_range}}.1\"\n  ip                 = \"{{ip_range}}.31/24\"\n  gateway            = \"{{ip_range}}.1\"\n}\n"
  },
  {
    "path": "extensions/ws01/providers/proxmox/ws01.tf",
    "content": "variable \"config_ws01_ext\" {\n  type = map(object({\n    name               = string\n    desc               = string\n    cores              = number\n    memory             = number\n    clone              = string\n    dns                = string\n    ip                 = string\n    gateway            = string\n  }))\n\n  default = {\n    \"ws01\" = {\n       name               = \"GOAD-WS01\"\n       desc               = \"WS01 - windows 10 - 192.168.10.31\"\n       cores              = 2\n       memory             = 4096\n       clone              = \"Windows10_22h2_x64\"\n       dns                = \"192.168.10.1\"\n       ip                 = \"192.168.10.31/24\"\n       gateway            = \"192.168.10.1\"\n    }\n  }\n}\n\nlocals {\n  vm_config = merge(config_ws01_ext, var.vm_config)\n}\n"
  },
  {
    "path": "extensions/ws01/providers/virtualbox/Vagrantfile",
    "content": "# add windows box\nboxes.append(\n  { :name => \"{{lab_name}}-WS01\",\n    :ip => \"{{ip_range}}.31\",\n    :box => \"mayfly/windows10\",\n    :os => \"windows\",\n    :cpus => 2,\n    :mem => 4000\n  }\n)"
  },
  {
    "path": "extensions/ws01/providers/vmware/Vagrantfile",
    "content": "boxes.append(\n  { :name => \"{{lab_name}}-WS01\",\n    :ip => \"{{ip_range}}.31\",\n    :box => \"mayfly/windows10\",\n    :os => \"windows\",\n    :cpus => 2,\n    :mem => 4000\n  }\n)"
  },
  {
    "path": "globalsettings.ini",
    "content": "[all:vars]\n; This is the global inventory file, data here will override all lab or provider inventory datas\n; modify this to add layouts to VMs\n; https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-language-pack-default-values\n; French  : 0000040C\n; US      : 00000409\n; German  : 00000407\n; Spanish : 0000040A\n; the first in the list will be the default layout (here: FR | US)\nkeyboard_layouts=[\"0000040C\", \"00000409\"]\n\n; Uncoment to not use SSL in ansible (usefull if you get Digest initialization failed: initialization error with vagrant)\n# ansible_winrm_transport=basic\n# ansible_port=5985\n\n; modify this to add a default route\nadd_route=no\nroute_gateway=192.168.56.1\nroute_network=10.0.0.0/8\n\n; modify this to enable http proxy\nenable_http_proxy=no\nproxy_ip=x.x.x.x\nproxy_port=8080\nad_http_proxy=\"http://{{proxy_ip}}:{{proxy_port}}\"\nad_https_proxy=\"http://{{proxy_ip}}:{{proxy_port}}\"\n\n; dns server fallback forwarder\n;dns_server_forwarder=1.1.1.1"
  },
  {
    "path": "goad/__init__.py",
    "content": ""
  },
  {
    "path": "goad/command/cmd.py",
    "content": "import subprocess\nimport psutil\nimport sys\nfrom goad.log import Log\nfrom goad.utils import Utils\nfrom goad.dependencies import Dependencies\n\nclass Command:\n\n    def __init__(self):\n        self.vagrant_bin = ''\n        self.terraform_bin = ''\n\n    # CHECK\n    def is_in_path(self, bin_file, show_log=True):\n        command = f'which {bin_file} >/dev/null'\n        try:\n            subprocess.run(command, shell=True, check=True)\n            if show_log:\n                Log.success(f'{bin_file} found in PATH')\n            return True\n        except subprocess.CalledProcessError as e:\n            if show_log:\n                Log.error(f'{bin_file} not found in PATH')\n            return False\n\n    def check_vagrant(self):\n        return self.is_in_path(self.vagrant_bin)\n\n    def check_vagrant_plugin(self, plugin_name, mandatory=True):\n        try:\n            result = subprocess.run([self.vagrant_bin, 'plugin', 'list'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)\n            if plugin_name in result.stdout:\n                Log.success(f'vagrant plugin {plugin_name} is installed')\n                return True\n            else:\n                if not mandatory:\n                    Log.warning(f'Missing vagrant plugin {plugin_name}')\n                else:\n                    Log.error(f'Missing vagrant plugin {plugin_name}')\n                    return False\n        except FileNotFoundError:\n            Log.error(\"Vagrant is not installed or not found in PATH.\")\n            return False\n\n    def check_vmware_utility(self):\n        pass\n\n    def check_ovftool(self):\n        pass\n\n    def check_gem(self, gem_name):\n        pass\n\n    def check_vmware(self):\n        pass\n\n    def check_virtualbox(self):\n        pass\n\n    def check_terraform(self):\n        return self.is_in_path(self.terraform_bin)\n\n    def check_aws(self):\n        return self.is_in_path('aws')\n\n    def check_azure(self):\n        return self.is_in_path('az')\n\n    def check_rsync(self):\n        return self.is_in_path('rsync')\n\n    def check_ansible(self):\n        if not Dependencies.provisioner_local_enabled and not Dependencies.provisioner_runner_enabled:\n            Log.info('skip ansible check as no local and runner provisionner enabled')\n            return True\n        checks = [\n            self.is_in_path('ansible-playbook'),\n            self.check_ansible_galaxy('ansible.windows'),\n            self.check_ansible_galaxy('community.general'),\n            self.check_ansible_galaxy('community.windows'),\n        ]\n        return all(checks)\n\n    def check_ansible_galaxy(self, collection):\n        try:\n            result = subprocess.run(['ansible-galaxy', 'collection', 'list'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd='./ansible')\n            if collection in result.stdout:\n                Log.success(f'Ansible galaxy collection {collection} is installed')\n                return True\n            else:\n                Log.error(f'Missing ansible-galaxy collection {collection}')\n                return False\n        except FileNotFoundError:\n            Log.error(\"ansible-galaxy is not installed or not found in PATH.\")\n            return False\n\n    def check_ludus(self):\n        # linux only\n        pass\n\n    def check_disk(self, min_disk_gb=120):\n        # If the system has multiple mountpoints, '.' will correctly calculate the available space on the current disk\n        disk_usage = psutil.disk_usage('.')\n        free_disk_gb = disk_usage.free / (1024 ** 3)  # Convert bytes to GB\n        if free_disk_gb < min_disk_gb:\n            Log.warning(f'not enough disk space, only {str(free_disk_gb)} Gb available')\n            return False\n        return True\n\n    def check_ram(self, min_ram_gb=24):\n        total_ram_gb = psutil.virtual_memory().total / (1024 ** 3)  # Convert bytes to GB\n        if total_ram_gb < min_ram_gb:\n            Log.error('not enough ram on the system')\n            return False\n        return True\n\n    # RUN\n    def run_shell(self, command, path):\n        try:\n            Log.info('CWD: ' + Utils.get_relative_path(str(path)))\n            Log.cmd(command)\n            subprocess.run(command, cwd=path, shell=True)\n        except subprocess.CalledProcessError as e:\n            Log.error(f\"An error occurred while running the command: {e}\")\n\n    def run_command(self, command, path):\n        result = None\n        try:\n            Log.info('CWD: ' + Utils.get_relative_path(str(path)))\n            Log.cmd(command)\n            result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout, shell=True)\n        except subprocess.CalledProcessError as e:\n            Log.error(f\"An error occurred while running the command: {e}\")\n            return False\n        return result.returncode == 0\n\n    def run_vagrant(self, args, path):\n        result = None\n        try:\n            command = [self.vagrant_bin]\n            command += args\n            Log.info('CWD: ' + Utils.get_relative_path(str(path)))\n            Log.cmd(' '.join(command))\n            result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout)\n        except subprocess.CalledProcessError as e:\n            Log.error(f\"An error occurred while running the command: {e}\")\n        return result.returncode == 0\n\n    def run_terraform(self, args, path):\n        result = None\n        try:\n            command = [self.terraform_bin]\n            command += args\n            Log.info('CWD: ' + Utils.get_relative_path(str(path)))\n            Log.cmd(' '.join(command))\n            result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout)\n        except subprocess.CalledProcessError as e:\n            Log.error(f\"An error occurred while running the command: {e}\")\n        return result.returncode == 0\n\n    def run_terraform_output(self, args, path):\n        result = None\n        try:\n            command = [self.terraform_bin, 'output', '-raw']\n            command += args\n            Log.info('CWD: ' + Utils.get_relative_path(str(path)))\n            Log.cmd(' '.join(command))\n            result = subprocess.run(command, cwd=path,\n                                    stdout=subprocess.PIPE,\n                                    stderr=subprocess.PIPE,\n                                    text=True\n                                    )\n            if result.returncode != 0:\n                print(f\"Error: {result.stderr}\")\n                return None\n\n            return result.stdout\n        except subprocess.CalledProcessError as e:\n            Log.error(f\"An error occurred while running the command: {e}\")\n        return None\n\n    def on_ludus(self):\n        return self.is_in_path('ludus', False)\n\n    def run_ludus(self, args, path, api_key, user_id='', impersonation=False):\n        # linux only\n        pass\n\n    def run_docker_ansible(self, args, path, ansible_path, sudo):\n        # linux only\n        pass\n\n    def run_ansible(self, args, path):\n        result = None\n        try:\n            command = 'ansible-playbook '\n            command += args\n            Log.info('CWD: ' + Utils.get_relative_path(str(path)))\n            Log.cmd(command)\n            result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout, shell=True)\n        except subprocess.CalledProcessError as e:\n            Log.error(f\"An error occurred while running the command: {e}\")\n            return False\n        return result.returncode == 0\n\n    def run_docker_ansible(self, args, path, sudo):\n        # Linux only\n        pass\n\n    def get_azure_account_output(self):\n        result = subprocess.run(\n            [\"az\", \"account\", \"list\", \"--output\", \"json\"],\n            stdout=subprocess.PIPE,\n            stderr=subprocess.PIPE,\n            text=True\n        )\n        if result.returncode != 0:\n            print(f\"Error: {result.stderr}\")\n            return None\n\n        return result.stdout\n\n    def scp(self, source, destination, ssh_key, path):\n        # scp files\n        Log.info(f'Launch scp {source} -> {destination}')\n        scp_command = f\"scp -o StrictHostKeyChecking=no -i {ssh_key}\"\n        command = f'{scp_command} {source} {destination}'\n        self.run_shell(command, path)\n\n    def rsync(self, source, destination, ssh_key, exclude=True):\n        # rsync = f'rsync -a --exclude-from='.gitignore' -e \"ssh -o 'StrictHostKeyChecking no' -i $CURRENT_DIR/ad/$lab/providers/$provider/ssh_keys/ubuntu-jumpbox.pem\" \"$CURRENT_DIR/\" goad@$public_ip:~/GOAD/'\n        Log.info(f'Launch Rsync {source} -> {destination}')\n        ssh_command = f\"ssh -o StrictHostKeyChecking=no -i {ssh_key}\"\n        exclude_from = ''\n        if exclude:\n            exclude_from = '--exclude-from=\".gitignore\"'\n        command = f'rsync -a {exclude_from} -e \"{ssh_command}\" {source} {destination}'\n        self.run_shell(command, source)\n"
  },
  {
    "path": "goad/command/cmd_factory.py",
    "content": "from goad.command.windows import WindowsCommand\nfrom goad.command.linux import LinuxCommand\nfrom goad.command.wsl import WslCommand\nfrom goad.utils import Utils\n\n\nclass CommandFactory:\n\n    @staticmethod\n    def get_command():\n        if Utils.is_wsl():\n            return WslCommand()\n        elif Utils.is_windows():\n            return WindowsCommand()\n        return LinuxCommand()\n"
  },
  {
    "path": "goad/command/linux.py",
    "content": "import sys\nimport os\nfrom goad.command.cmd import Command\nimport subprocess\n\nfrom goad.goadpath import GoadPath\nfrom goad.log import Log\nfrom goad.utils import Utils\n\n\nclass LinuxCommand(Command):\n\n    def __init__(self):\n        super().__init__()\n        self.vagrant_bin = 'vagrant'\n        self.terraform_bin = 'terraform'\n\n    # CHECK\n    def check_gem(self, gem_name):\n        try:\n            result = subprocess.run(['gem', 'list'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)\n            if gem_name in result.stdout:\n                Log.success(f'ruby gem {gem_name} is installed')\n                return True\n            else:\n                Log.warning(f'ruby gem {gem_name} not installed')\n                return False\n        except FileNotFoundError:\n            Log.error(\"Ruby or gem is not installed or not found in PATH.\")\n            return False\n\n    def check_vmware(self):\n        return self.is_in_path('vmrun')\n\n    def check_vmware_utility(self):\n        try:\n            result = subprocess.run(\n                ['systemctl', 'is-active', '--quiet', 'vagrant-vmware-utility'],\n                check=True\n            )\n            Log.success(f'vmware utility is installed')\n            return True\n        except subprocess.CalledProcessError:\n            Log.error(\"vagrant-vmware-utility is not installed\")\n            return False\n\n    def check_ovftool(self):\n        try:\n            result = subprocess.run(['ovftool', '-v'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd='.')\n            fields = result.stdout.split(' ')\n            if len(fields) > 2:\n                version = fields[2]\n                Log.success(f'Ovftool version {version} is installed')\n                return True\n            else:\n                Log.error(f'Failed to parse ovftool version')\n                return False\n        except FileNotFoundError:\n            Log.error(\"ovftool is not installed or not found in PATH.\")\n            return False\n\n    def check_virtualbox(self):\n        return self.is_in_path('VBoxManage')\n\n    def check_ludus(self):\n        return self.is_in_path('ludus')\n\n    # RUN\n    def run_ludus(self, args, path, api_key, user_id='', impersonation=False):\n        env = os.environ.copy()\n        if \"LUDUS_API_KEY\" not in os.environ:\n            Log.info('Using api key from config file')\n            env[\"LUDUS_API_KEY\"] = api_key\n        else:\n            Log.info('Using api key from env')\n        result = None\n        try:\n            command = 'ludus '\n            if impersonation:\n                command += f'--user {user_id} '\n            command += args\n            Log.info('CWD: ' + Utils.get_relative_path(str(path)))\n            Log.cmd(command)\n            result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout, shell=True, env=env)\n        except subprocess.CalledProcessError as e:\n            Log.error(f\"An error occurred while running the command: {e}\")\n        return result.returncode == 0\n\n    def run_ludus_result(self, command, path, api_key, do_log=True, user_id='', impersonation=False):\n        result = None\n        env = os.environ.copy()\n        if \"LUDUS_API_KEY\" not in os.environ:\n            Log.info('Using api key from config file')\n            env[\"LUDUS_API_KEY\"] = api_key\n        else:\n            Log.info('Using api key from env')\n        try:\n            cmd = ['ludus']\n            if impersonation:\n                cmd += ['--user', user_id]\n            cmd += command\n            if do_log:\n                Log.info('CWD: ' + Utils.get_relative_path(str(path)))\n                Log.cmd(' '.join(cmd))\n            result = subprocess.run(cmd, cwd=path,\n                                    stdout=subprocess.PIPE,\n                                    stderr=subprocess.PIPE,\n                                    text=True,\n                                    env=env\n                                    )\n            if result.returncode != 0:\n                print(f\"Error: {result.stderr}\")\n                return None\n\n            return result.stdout\n        except subprocess.CalledProcessError as e:\n            Log.error(f\"An error occurred while running the command: {e}\")\n        return None\n\n    def run_docker_ansible(self, args, path, ansible_path, sudo):\n        result = None\n        try:\n            ansible_command = 'ansible-playbook '\n            ansible_command += args\n            command = f\"{sudo} docker run -ti --rm --network host -h goadansible -v {GoadPath.get_project_path()}:/goad -w {ansible_path} goadansible /bin/bash -c '{ansible_command}'\"\n            Log.cmd(command)\n            result = subprocess.run(command, cwd=path, stderr=sys.stderr, stdout=sys.stdout, shell=True)\n        except subprocess.CalledProcessError as e:\n            Log.error(f\"An error occurred while running the command: {e}\")\n            return False\n        return result.returncode == 0\n\n"
  },
  {
    "path": "goad/command/windows.py",
    "content": "import os\nfrom goad.command.cmd import Command\nimport subprocess\nfrom goad.log import Log\n\n\nclass WindowsCommand(Command):\n\n    def __init__(self):\n        super().__init__()\n        self.vagrant_bin = 'vagrant.exe'\n        self.terraform_bin = 'terraform.exe'\n\n    def file_exist(self, file):\n        exist = os.path.isfile(file)\n        if exist:\n            Log.success(f'File {file} present in the file system')\n        return exist\n\n    def is_in_path(self, bin_file):\n        command = f'where {bin_file} >nul'\n        try:\n            subprocess.run(command, shell=True, check=True)\n            Log.success(f'{bin_file} found in PATH')\n            return True\n        except subprocess.CalledProcessError as e:\n            Log.error(f'{bin_file} not found in PATH')\n            return False\n\n    # CHECK\n    def check_gem(self, gem_name):\n        # not needed\n        pass\n\n    def check_vmware(self):\n        return self.file_exist(\"c:\\\\Program Files (x86)\\\\VMware\\\\VMware Workstation\\\\vmrun.exe\")\n\n    def check_vmware_utility(self):\n        return self.file_exist(\"c:\\\\Program Files\\\\VagrantVMwareUtility\\\\vagrant-vmware-utility.exe\")\n\n    def check_ovftool(self):\n        return self.file_exist(\"c:\\\\Program Files\\\\VMware\\\\VMware OVF Tool\\\\ovftool.exe\")\n\n    def check_virtualbox(self):\n        return self.file_exist(\"c:\\\\Program Files\\\\Oracle\\\\VirtualBox\\\\VBoxManage.exe\")\n\n    def check_terraform(self):\n        return self.is_in_path('terraform.exe')\n\n    def check_ludus(self):\n        return False\n"
  },
  {
    "path": "goad/command/wsl.py",
    "content": "import sys\nimport os\nfrom goad.command.cmd import Command\nimport subprocess\nfrom goad.goadpath import GoadPath\nfrom goad.log import Log\nfrom goad.utils import Utils\n\n\nclass WslCommand(Command):\n\n    def __init__(self):\n        super().__init__()\n        self.vagrant_bin = 'vagrant.exe'\n        self.terraform_bin = 'terraform.exe'\n\n    def file_exist(self, file):\n        exist = os.path.isfile(file)\n        if exist:\n            Log.success(f'File {file} present in the file system')\n        return exist\n\n    # CHECK\n    def check_gem(self, gem_name):\n        # not needed\n        pass\n\n    def check_vmware(self):\n        return self.file_exist(\"/mnt/c/Program Files (x86)/VMware/VMware Workstation/vmrun.exe\")\n\n    def check_vmware_utility(self):\n        return self.file_exist(\"/mnt/c/Program Files/VagrantVMwareUtility/vagrant-vmware-utility.exe\")\n\n    def check_ovftool(self):\n        return self.file_exist(\"/mnt/c/Program Files/VMware/VMware OVF Tool/ovftool.exe\")\n\n    def check_virtualbox(self):\n        return self.file_exist(\"/mnt/c/Program Files/Oracle/VirtualBox/VBoxManage.exe\")\n\n    def check_terraform(self):\n        return self.is_in_path('terraform.exe')\n\n    def check_ludus(self):\n        return False\n\n    # RUN\n    # see Command\n"
  },
  {
    "path": "goad/config.py",
    "content": "import configparser\nfrom goad.goadpath import GoadPath\nfrom goad.utils import *\nfrom goad.log import Log\nfrom goad.dependencies import Dependencies\n\n\nclass Config:\n    config = None\n\n    def __init__(self):\n        if not os.path.isdir(GoadPath.get_config_path()):\n            Log.info(f'goad config path not found, create dir {GoadPath.get_config_path()}')\n            os.mkdir(GoadPath.get_config_path(), 0o750)\n        if not os.path.isfile(GoadPath.get_config_file()):\n            Log.info(f'goad config file not found, create file {GoadPath.get_config_file()}')\n            self.create_config_file()\n\n    def get_config_parser(self):\n        return self.config\n\n    def create_config_file(self):\n        cfgfile = open(GoadPath.get_config_file(), \"w\")\n        config = configparser.ConfigParser(allow_no_value=True)\n\n        config.add_section('default')\n        config.set('default', '; lab: GOAD / GOAD-Light / MINILAB / NHA / SCCM')\n        config.set('default', 'lab', 'GOAD')\n\n        config.set('default', '; provider : virtualbox / vmware / vmware_esxi / aws / azure / proxmox')\n        config.set('default', 'provider', 'vmware')\n\n        config.set('default', \"; provisioner method : local / remote\")\n        config.set('default', 'provisioner', 'local')\n\n        config.set('default', '; ip_range (3 first ip digits)')\n        config.set('default', 'ip_range', '192.168.56')\n\n        config.add_section('aws')\n        config.set('aws', 'aws_region', 'eu-west-3')\n        config.set('aws', 'aws_zone', 'eu-west-3c')\n\n        config.add_section('azure')\n        config.set('azure', 'az_location', 'westeurope')\n\n        config.add_section('proxmox')\n        config.set('proxmox', 'pm_api_url', 'https://192.168.1.1:8006/api2/json')\n        config.set('proxmox', 'pm_user', 'infra_as_code@pve')\n        config.set('proxmox', 'pm_node', 'GOAD')\n        config.set('proxmox', 'pm_pool', 'GOAD')\n        config.set('proxmox', 'pm_full_clone', 'false')\n        config.set('proxmox', 'pm_storage', 'local')\n        config.set('proxmox', 'pm_vlan', '10')\n        config.set('proxmox', 'pm_network_bridge', 'vmbr3')\n        config.set('proxmox', 'pm_network_model', 'e1000')\n\n        config.add_section('proxmox_templates_id')\n        config.set('proxmox_templates_id', 'WinServer2019_x64', '201900')\n        config.set('proxmox_templates_id', 'WinServer2016_x64', '201600')\n        config.set('proxmox_templates_id', 'WinServer2022_x64', '202201')\n        config.set('proxmox_templates_id', 'WinServer2025_x64', '202501')\n        config.set('proxmox_templates_id', 'WinServer2019_x64_utd', '201901')\n        config.set('proxmox_templates_id', 'Windows10_22h2_x64', '102221')\n        config.set('proxmox_templates_id', 'Windows11_23h2_x64', '112321')\n        config.set('proxmox_templates_id', 'Windows11_24h2_x64', '112421')\n        config.set('proxmox_templates_id', 'Windows11_25h2_x64', '112521')\n        config.set('proxmox_templates_id', 'Ubuntu_2204_x64', '922040')\n        config.set('proxmox_templates_id', 'Ubuntu_2404_x64', '924040')\n\n        config.add_section('ludus')\n        config.set('ludus', '; api key must not have % if you have a % in it, change it by a %%')\n        config.set('ludus', 'ludus_api_key', 'change_me')\n        config.set('ludus', 'use_impersonation', 'yes')\n\n        config.add_section('vmware_esxi')\n        config.set('vmware_esxi', 'esxi_hostname', '10.10.10.10')\n        config.set('vmware_esxi', 'esxi_username', 'root')\n        config.set('vmware_esxi', 'esxi_password', 'password')\n        config.set('vmware_esxi', 'esxi_net_nat', 'VM Network')\n        config.set('vmware_esxi', 'esxi_net_domain', 'GOAD-LAN')\n        config.set('vmware_esxi', 'esxi_datastore', 'datastore1')\n        config.write(cfgfile)\n        cfgfile.close()\n\n    def merge_config(self, args):\n        \"\"\"\n        Merge the configuration with the script arguments\n        :param args: goad.py arguments\n        :return: goad.Config object\n        \"\"\"\n        self.config = configparser.ConfigParser()\n        self.config.read(GoadPath.get_config_file())\n        if args is not None:\n            if args.lab:\n                self.set_value('default', LAB, args.lab)\n            if args.provider:\n                self.set_value('default', PROVIDER, args.provider)\n            if args.method:\n                self.set_value('default', PROVISIONER, args.method)\n            if args.ip_range:\n                self.set_value('default', IP_RANGE, args.ip_range)\n            if args.disable_dependencies:\n                for disable_dependence in args.disable_dependencies:\n                    if disable_dependence == 'vmware':\n                        Dependencies.vmware_enabled = False\n                    elif disable_dependence == 'vmware_esxi':\n                        Dependencies.vmware_esxi_enabled = False\n                    elif disable_dependence == 'virtualbox':\n                        Dependencies.virtualbox_enabled = False\n                    elif disable_dependence == 'azure':\n                        Dependencies.azure_enabled = False\n                    elif disable_dependence == 'aws':\n                        Dependencies.aws_enabled = False\n                    elif disable_dependence == 'ludus':\n                        Dependencies.ludus_enabled = False\n                    elif disable_dependence == 'proxmox':\n                        Dependencies.proxmox_enabled_enabled = False\n                    elif disable_dependence == 'local':\n                        Dependencies.provisioner_local_enabled = False\n                    elif disable_dependence == 'runner':\n                        Dependencies.provisioner_runner_enabled = False\n                    elif disable_dependence == 'remote':\n                        Dependencies.provisioner_remote_enabled = False\n                    elif disable_dependence == 'docker':\n                        Dependencies.provisioner_docker_enabled = False\n        return self\n\n    def get_value(self, section, key, fallback=None):\n        return self.config.get(section, key, fallback=fallback)\n\n    def set_value(self, section, key, value):\n        return self.config.set(section, key, value)\n\n    def show(self):\n        for section in self.config.sections():\n            Log.basic(f'[yellow]\\\\[{section}][/yellow]')\n            for key in self.config[section]:\n                Log.basic(f' {key} : {self.config[section][key]}')\n            Log.basic('')\n"
  },
  {
    "path": "goad/dependencies.py",
    "content": "from goad.utils import Utils\n\n\nclass Dependencies:\n    # Can change enabled providers (useful if you don't want some dependencies)\n    vmware_enabled = True\n    vmware_esxi_enabled = True\n    virtualbox_enabled = True\n    azure_enabled = True\n    aws_enabled = True\n    proxmox_enabled = True\n    ludus_enabled = True\n    # Can change enabled provisioners (useful if you don't want some dependencies)\n    provisioner_local_enabled = False if Utils.is_windows() else True\n    provisioner_runner_enabled = False if Utils.is_windows() else True\n    provisioner_remote_enabled = True\n    provisioner_vm_enabled = True\n    provisioner_docker_enabled = False if Utils.is_wsl() or Utils.is_windows() else True\n"
  },
  {
    "path": "goad/exceptions.py",
    "content": "class ProviderPathNotFound(Exception):\n    pass\n\n\nclass AuthenticationFailed(Exception):\n    pass\n\n\nclass JumpBoxInitFailed(Exception):\n    pass\n"
  },
  {
    "path": "goad/extension.py",
    "content": "from goad.utils import *\nfrom goad.goadpath import GoadPath\nfrom goad.log import Log\nimport json\n\n\nclass Extension:\n\n    def __init__(self, extension_name):\n        self.name = extension_name\n        self.providers_name_list = self.load_extension_providers(extension_name)\n        self.compatibility = []\n        self.description = ''\n        self.load_extension_config_file(extension_name)\n\n    def load_extension_providers(self, extension_name):\n        providers_name_list = []\n        for provider_name in Utils.list_folders(GoadPath.get_extension_providers_path(extension_name)):\n            if provider_name in ALLOWED_PROVIDERS:\n                providers_name_list.append(provider_name)\n        return providers_name_list\n\n    def load_extension_config_file(self, extension_name):\n        extension_json_file = GoadPath.get_extension_config_file(extension_name)\n        if os.path.isfile(extension_json_file):\n            with open(extension_json_file, 'r') as extension_json_openfile:\n                # Reading from json file\n                extension_info = json.load(extension_json_openfile)\n                self.compatibility = extension_info['compatibility']\n                self.description = extension_info['description']\n\n    def is_available(self, lab_name):\n        return '*' in self.compatibility or lab_name in self.compatibility\n\n    def list_providers_name(self):\n        return self.providers_name_list\n\n    def get_playbook(self, install=True):\n        if install:\n            return 'install.yml'\n        else:\n            return 'uninstall.yml'\n\n    def get_ansible_path(self):\n        return GoadPath.get_extension_ansible_path(self.name)\n\n    def show(self):\n        name = f'{self.name}'.ljust(30, '.')\n        Log.info(f'{name} {self.description}')\n"
  },
  {
    "path": "goad/goadpath.py",
    "content": "from goad.utils import *\n\nsep = os.path.sep\nproject_path = os.path.normpath(os.path.dirname(os.path.abspath(__file__)) + sep + '..')\n\n\nclass GoadPath:\n\n    @staticmethod\n    def get_config_path():\n        home = str(Path.home())\n        return home + sep + '.goad'\n\n    @staticmethod\n    def get_config_file():\n        return GoadPath.get_config_path() + sep + 'goad.ini'\n\n    @staticmethod\n    def get_global_inventory_path():\n        return project_path + os.path.sep + 'globalsettings.ini'\n\n    @staticmethod\n    def get_workspace_path():\n        return project_path + sep + 'workspace'\n\n    @staticmethod\n    def get_project_path():\n        return project_path + sep\n\n    @staticmethod\n    def get_template_path(provider):\n        \"\"\"\n        :return:  <project>/template/provider/<provider>/\n        \"\"\"\n        return project_path + sep + 'template' + sep + 'provider' + sep + provider + sep\n\n    # config\n    @staticmethod\n    def get_playbooks_lab_config():\n        \"\"\"\n        :return:  <project>/playbooks.yml\n        \"\"\"\n        return project_path + os.path.sep + 'playbooks.yml'\n\n    # LAB recipe\n    @staticmethod\n    def get_labs_path():\n        \"\"\"\n        :return: <project>/ad\n        \"\"\"\n        return project_path + sep + 'ad'\n\n    @staticmethod\n    def get_lab_path(lab_name):\n        \"\"\"\n        :return: <project>/ad/<lab_name>\n        \"\"\"\n        return GoadPath.get_labs_path() + sep + lab_name\n\n    @staticmethod\n    def get_lab_data_path(lab_name):\n        \"\"\"\n        :return: <project>/ad/<lab_name>/data\n        \"\"\"\n        return GoadPath.get_lab_path(lab_name) + sep + 'data'\n\n    @staticmethod\n    def get_lab_providers_path(lab_name):\n        \"\"\"\n        :return: <project>/ad/<lab_name>/providers\n        \"\"\"\n        return project_path + os.path.sep + 'ad' + os.path.sep + lab_name + os.path.sep + 'providers'\n\n    @staticmethod\n    def get_lab_provider_path(lab_name, provider_name):\n        \"\"\"\n        :return:  <project>/ad/<lab_name>/providers/<provider>\n        \"\"\"\n        return GoadPath.get_lab_providers_path(lab_name) + sep + provider_name\n\n    @staticmethod\n    def get_provider_inventory_file(lab_name, provider_name):\n        \"\"\"\n        :return: <project>/ad/<lab_name>/providers/<provider>/inventory\n        \"\"\"\n        return GoadPath.get_lab_provider_path(lab_name, provider_name) + sep + 'inventory'\n\n    @staticmethod\n    def get_lab_inventory_file(lab_name):\n        \"\"\"\n        :return: <project>/ad/<lab_name>/data/inventory\n        \"\"\"\n        return GoadPath.get_lab_path(lab_name) + os.path.sep + 'data' + os.path.sep + 'inventory'\n\n    # script\n    @staticmethod\n    def get_script_path():\n        \"\"\"\n        :return: <project>/scripts\n        \"\"\"\n        return project_path + os.path.sep + 'scripts'\n\n    @staticmethod\n    def get_script_file(script):\n        \"\"\"\n        :return: <project>/scripts/<script>\n        \"\"\"\n        return project_path + os.path.sep + 'scripts' + os.path.sep + script\n\n    # ANSIBLE\n    @staticmethod\n    def get_provisioner_path():\n        \"\"\"\n        :return: <project>/ansible/\n        \"\"\"\n        return project_path + os.path.sep + 'ansible' + sep\n\n    # Instances\n    @staticmethod\n    def get_instance_path(instance_id):\n        \"\"\"\n        :return: <project>/workspace/<instance_id>\n        \"\"\"\n        return GoadPath.get_workspace_path() + sep + instance_id\n\n    @staticmethod\n    def get_instance_provider_path(instance_id):\n        return GoadPath.get_instance_path(instance_id) + sep + 'provider'\n\n    # EXTENSIONS\n    @staticmethod\n    def get_extensions_path():\n        return project_path + os.path.sep + 'extensions'\n\n    @staticmethod\n    def get_extension_path(extension_name):\n        \"\"\"\n        :return: <project>/extensions/<extension_name>/\n        \"\"\"\n        return GoadPath.get_extensions_path() + os.path.sep + extension_name + os.path.sep\n\n    @staticmethod\n    def get_extension_config_file(extension_name):\n        \"\"\"\n        :return: <project>/extensions/<extension_name>/\n        \"\"\"\n        return GoadPath.get_extensions_path() + os.path.sep + extension_name + os.path.sep + 'extension.json'\n\n    @staticmethod\n    def get_extension_providers_path(extension_name):\n        \"\"\"\n        :return: <project>/extensions/<extension_name>/provider\n        \"\"\"\n        return GoadPath.get_extension_path(extension_name) + 'providers'\n\n    @staticmethod\n    def get_extension_providers_provider_path(extension_name, provider_name):\n        \"\"\"\n        :return:  <project>/extensions/<extension_name>/providers/<provider>/\n        \"\"\"\n        return GoadPath.get_extension_providers_path(extension_name) + os.path.sep + provider_name + os.path.sep\n\n    @staticmethod\n    def get_extension_ansible_path(extension_name):\n        \"\"\"\n        :return <project>/extensions/<extension_name>/ansible\n        \"\"\"\n        return GoadPath.get_extension_path(extension_name) + 'ansible'\n"
  },
  {
    "path": "goad/infos.py",
    "content": "from goad.log import *\nfrom rich.table import Table\n\n\ndef show_labs_providers_list(labs):\n    for lab in labs:\n        Log.success(f'*** {lab.lab_name} ***')\n        for provider in lab.providers.keys():\n            Log.info(f' {provider}')\n\n\ndef show_labs_providers_table(labs):\n    table = Table(title=\"Labs providers\")\n    table.add_column('Lab')\n    headers = []\n    for lab in labs:\n        for provider in lab.providers.keys():\n            if provider not in headers:\n                headers.append(provider)\n\n    for header in headers:\n        table.add_column(header)\n\n    for lab in labs:\n        row_value = [lab.lab_name]\n        for header in headers:\n            if header in lab.providers.keys():\n                row_value.append('[green]✓[/green]')\n            else:\n                row_value.append('[red]X[/red]')\n        table.add_row(*row_value)\n\n    print(table)\n"
  },
  {
    "path": "goad/instance.py",
    "content": "import json\nimport shutil\nimport os\nfrom jinja2 import Template, Environment, FileSystemLoader\nfrom goad.goadpath import *\nfrom goad.log import Log\nfrom goad.exceptions import ProviderPathNotFound, JumpBoxInitFailed\nfrom goad.provisioner.provisioner_factory import ProvisionerFactory\nfrom goad.utils import *\n\n\nclass LabInstance:\n\n    def __init__(self, instance_id, lab_name, config, provider_name, provisioner_name, ip_range, extensions=None, status='', default=False):\n        if instance_id is None:\n            random_id = ''.join(random.choices(string.hexdigits, k=6))\n            self.instance_id = f'{random_id}-{lab_name}-{provider_name}'.lower()\n        else:\n            self.instance_id = instance_id\n        self.lab_name = lab_name\n        self.config = config\n        self.provider_name = provider_name\n        self.provisioner_name = provisioner_name\n        self.ip_range = ip_range\n        self.status = status\n        if extensions is None:\n            extensions = []\n        self.extensions = extensions\n        self.is_default = default\n\n        # paths\n        self.instance_path = GoadPath.get_instance_path(self.instance_id)\n        self.instance_provider_path = GoadPath.get_instance_provider_path(self.instance_id)\n\n        # prepare model objects\n        self.lab = None\n        self.provider = None\n        self.provisioner = None\n\n    def load(self, labs, creation=False):\n        instance_path = GoadPath.get_instance_path(self.instance_id)\n        if not os.path.isdir(instance_path):\n            Log.error('instance path not found abort')\n            return False\n\n        self.lab = labs.get_lab(self.lab_name)\n        if self.lab is None:\n            Log.error('lab not found')\n            return False\n\n        self.provider = self.lab.get_provider(self.provider_name)\n        if self.provider is None:\n            Log.error('provider not found')\n            return False\n\n        if self.provider_name == AZURE:\n            self.provider.set_resource_group(self.lab_name + '-' + self.instance_id)\n        if self.provider_name == AWS:\n            self.provider.set_tag(self.lab_name + '-' + self.instance_id)\n        if self.provider_name == LUDUS:\n            user_id = self.lab_name + self.instance_id.split('-')[0]\n            user_id = user_id.replace('-', '').replace('_', '')\n            self.provider.set_lab_user(user_id[:19])\n\n        if not os.path.isdir(self.instance_provider_path):\n            Log.error('instance provider path {instance_provider_path} not found')\n            return False\n\n        self.provider.set_instance_path(self.instance_provider_path)\n\n        self.provisioner = ProvisionerFactory.get_provisioner(self.provisioner_name, self, creation)\n\n        if self.provisioner is None:\n            Log.error('instance provisioner does not exist')\n            return False\n\n        self.provisioner.set_instance_path(instance_path)\n        return True\n\n    def is_terraform(self):\n        return self.provider_name == AWS or self.provider_name == AZURE or self.provider_name == PROXMOX\n\n    def is_vagrant(self):\n        return self.provider_name == VMWARE or self.provider_name == VMWARE_ESXI or self.provider_name == VIRTUALBOX\n\n    def is_ludus(self):\n        return self.provider_name == LUDUS\n\n    def enable_extension(self, extension_name):\n        if extension_name not in self.extensions:\n            self.extensions.append(extension_name)\n            self.save_json_instance()\n        Log.info('Extension enabled update folders')\n        self.update_instance_folder()\n\n    def disable_extension(self, extension_name):\n        if extension_name in self.extensions:\n            self.extensions.remove(extension_name)\n            self.save_json_instance()\n            self.update_instance_folder()\n\n    def save_json_instance(self):\n        instance_info = {\n            \"id\": self.instance_id,\n            \"lab\": self.lab_name,\n            \"provider\": self.provider_name,\n            \"provisioner\": self.provisioner_name,\n            \"ip_range\": self.ip_range,\n            \"extensions\": self.extensions,\n            \"status\": self.status,\n            \"is_default\": self.is_default\n        }\n        json_object = json.dumps(instance_info, indent=4)\n        with open(self.instance_path + sep + \"instance.json\", \"w\") as outfile:\n            outfile.write(json_object)\n\n    def _create_vagrantfile(self):\n        # load lab vagrantfile\n        lab_environment = Environment(loader=FileSystemLoader(GoadPath.get_lab_provider_path(self.lab_name, self.provider_name)))\n        lab_vagrantfile_template = lab_environment.get_template(\"Vagrantfile\")\n        lab_vagrantfile_content = lab_vagrantfile_template.render(\n            lab_name=self.lab_name,\n            ip_range=self.ip_range\n        )\n\n        # load lab extensions\n        lab_extensions_content = ''\n        for extension in self.extensions:\n            extension_provider_folder = GoadPath.get_extension_providers_provider_path(extension, self.provider_name)\n            if os.path.isfile(f'{extension_provider_folder}{sep}Vagrantfile'):\n                extension_environment = Environment(loader=FileSystemLoader(extension_provider_folder))\n                lab_extension_vagrantfile_template = extension_environment.get_template(\"Vagrantfile\")\n                lab_extensions_content += lab_extension_vagrantfile_template.render(\n                    lab_name=self.lab_name,\n                    ip_range=self.ip_range\n                ) + \"\\n\"\n\n        # load extensions Vagrantfile into instance\n        use_provisioning_vm = True if self.provisioner_name == PROVISIONING_VM else False\n        environment = Environment(loader=FileSystemLoader(GoadPath.get_template_path(self.provider_name)))\n        vagrantfile_template = environment.get_template(\"Vagrantfile\")\n        vagrantfile_content = vagrantfile_template.render(\n            lab_name=self.lab_name,\n            lab=lab_vagrantfile_content,\n            extensions=lab_extensions_content,\n            provider_name=self.provider_name,\n            ip_range=self.ip_range,\n            use_provisioning_vm=use_provisioning_vm\n        )\n\n        # create vagrantfile\n        instance_vagrant_file = self.instance_provider_path + sep + 'Vagrantfile'\n        with open(instance_vagrant_file, mode=\"w\", encoding=\"utf-8\") as vagrantfile:\n            vagrantfile.write(vagrantfile_content)\n            Log.info(f'Instance vagrantfile created : {Utils.get_relative_path(instance_vagrant_file)}')\n\n    def _create_esxi_env(self):\n        # get esxi config\n        config = self.config\n        esxi_hostname = config.get_value('vmware_esxi', 'esxi_hostname')\n        esxi_username = config.get_value('vmware_esxi', 'esxi_username')\n        esxi_password = config.get_value('vmware_esxi', 'esxi_password')\n        esxi_net_nat = config.get_value('vmware_esxi', 'esxi_net_nat')\n        esxi_net_domain = config.get_value('vmware_esxi', 'esxi_net_domain')\n        esxi_datastore = config.get_value('vmware_esxi', 'esxi_datastore')\n        \n        # load .env template\n        environment = Environment(loader=FileSystemLoader(GoadPath.get_template_path(self.provider_name)))\n        envfile_template = environment.get_template(\".env\")\n        envfile_content = envfile_template.render(\n            esxi_hostname = esxi_hostname,\n            esxi_username = esxi_username,\n            esxi_password = esxi_password,\n            esxi_net_nat = esxi_net_nat,\n            esxi_net_domain = esxi_net_domain,\n            esxi_datastore = esxi_datastore\n        )\n\n        # create .env file\n        instance_env_file = self.instance_provider_path + sep + '.env'\n        with open(instance_env_file, mode=\"w\", encoding=\"utf-8\") as vagrantfile:\n            vagrantfile.write(envfile_content)\n            Log.info(f'Instance .env created : {Utils.get_relative_path(instance_env_file)}')\n\n    def _create_ludus_config_file(self):\n        # load lab vagrantfile\n        lab_environment = Environment(loader=FileSystemLoader(GoadPath.get_lab_provider_path(self.lab_name, self.provider_name)))\n        lab_ludus_config_file_template = lab_environment.get_template(\"config.yml\")\n        lab_ludus_config_file_content = lab_ludus_config_file_template.render(\n            lab_name=self.lab_name,\n            range_id=\"{{ range_id }}\",\n            ip_range=self.ip_range\n        )\n\n        # load lab extensions\n        lab_extensions_ludus_config_file_content = ''\n        for extension in self.extensions:\n            extension_provider_folder = GoadPath.get_extension_providers_provider_path(extension, self.provider_name)\n            extension_environment = Environment(loader=FileSystemLoader(extension_provider_folder))\n            lab_extension_ludus_config_file_template = extension_environment.get_template(\"config.yml\")\n            lab_extensions_ludus_config_file_content += lab_extension_ludus_config_file_template.render(\n                lab_name=self.lab_name,\n                range_id=\"{{ range_id }}\",\n                ip_range=self.ip_range\n            ) + \"\\n\"\n\n        # load lab + extension into instance config\n        environment = Environment(loader=FileSystemLoader(GoadPath.get_template_path(self.provider_name)))\n        ludus_config_file_template = environment.get_template(\"config.yml\")\n        ludus_config_file_template_content = ludus_config_file_template.render(\n            lab_name=self.lab_name,\n            lab=lab_ludus_config_file_content,\n            extensions=lab_extensions_ludus_config_file_content,\n            provider_name=self.provider_name\n        )\n\n        # create vagrantfile\n        instance_ludus_file = self.instance_provider_path + sep + 'config.yml'\n        with open(instance_ludus_file, mode=\"w\", encoding=\"utf-8\") as ludusfile:\n            ludusfile.write(ludus_config_file_template_content)\n            Log.info(f'Instance vagrantfile created : {Utils.get_relative_path(instance_ludus_file)}')\n\n    def _create_terraform_folder(self):\n        # load lab files\n        lab_environment = Environment(loader=FileSystemLoader(GoadPath.get_lab_provider_path(self.lab_name, self.provider_name)))\n        lab_windows_template = lab_environment.get_template(\"windows.tf\")\n        windows_vm = lab_windows_template.render(\n            ip_range=self.ip_range\n        )\n\n        linux_vm = ''\n        if os.path.isfile(GoadPath.get_lab_provider_path(self.lab_name, self.provider_name) + sep + 'linux.tf'):\n            lab_environment = Environment(loader=FileSystemLoader(GoadPath.get_lab_provider_path(self.lab_name, self.provider_name)))\n            lab_windows_template = lab_environment.get_template(\"linux.tf\")\n            linux_vm = lab_windows_template.render(\n                ip_range=self.ip_range\n            )\n\n        # load lab extensions content\n        for extension in self.extensions:\n            extension_provider_folder = GoadPath.get_extension_providers_provider_path(extension, self.provider_name)\n            extension_environment = Environment(loader=FileSystemLoader(extension_provider_folder))\n            if os.path.isfile(extension_provider_folder + sep + 'linux.tf'):\n                lab_extension_linux_template = extension_environment.get_template(\"linux.tf\")\n                linux_vm += \"\\n\" + lab_extension_linux_template.render(\n                    lab_name=self.lab_name,\n                    ip_range=self.ip_range\n                ) + \"\\n\"\n            if os.path.isfile(extension_provider_folder + sep + 'windows.tf'):\n                lab_extension_windows_template = extension_environment.get_template(\"windows.tf\")\n                windows_vm += \"\\n\" + lab_extension_windows_template.render(\n                    lab_name=self.lab_name,\n                    ip_range=self.ip_range\n                ) + \"\\n\"\n\n        # load template folder\n        environment = Environment(loader=FileSystemLoader(GoadPath.get_template_path(self.provider_name)))\n\n        for template in Utils.list_files(GoadPath.get_template_path(self.provider_name)):\n            tf_template = environment.get_template(template)\n            tf_content = tf_template.render(\n                windows_vms=windows_vm,\n                linux_vms=linux_vm,\n                lab_identifier=self.lab_name + '-' + self.instance_id,\n                lab_name=self.lab_name,\n                ip_range=self.ip_range,\n                provider_name=self.provider_name,\n                config=self.config\n            )\n            # create terraform files\n            instance_tf_file = self.instance_provider_path + sep + template\n            with open(instance_tf_file, mode=\"w\", encoding=\"utf-8\") as tf_file:\n                tf_file.write(tf_content)\n                Log.success(f'Instance terraform file created : {Utils.get_relative_path(instance_tf_file)}')\n\n    def _create_provider_dir(self):\n        # create provider dir\n        # workspace/provider\n        if not os.path.isdir(self.instance_provider_path):\n            os.mkdir(self.instance_provider_path, 0o755)\n        # workspace/ssh_keys\n        ssh_folder = self.instance_path + sep + 'ssh_keys'\n        if not os.path.isdir(ssh_folder):\n            os.mkdir(ssh_folder, 0o750)\n        Log.info('Create instance providing files')\n        if self.is_vagrant():\n            self._create_vagrantfile()\n        if self.provider_name == VMWARE_ESXI:\n            self._create_esxi_env()\n        if self.is_ludus():\n            self._create_ludus_config_file()\n        if self.is_terraform():\n            self._create_terraform_folder()\n\n    def _create_provisioning_lab_inventory(self, inventory_file):\n        Log.info(f'Create lab provisioning file {inventory_file}')\n        # create lab inventory\n        lab_provider_path = GoadPath.get_lab_data_path(self.lab_name)\n        environment = Environment(loader=FileSystemLoader(lab_provider_path))\n        # create inventory template\n        inventory_template = environment.get_template(inventory_file)\n        instance_inventory_content = inventory_template.render(\n            lab_name=self.lab_name,\n            ip_range=self.ip_range,\n            provider_name=self.provider_name\n        )\n        # create instance inventory file\n        instance_inventory_file = self.instance_path + sep + inventory_file\n        with open(instance_inventory_file, mode=\"w\", encoding=\"utf-8\") as instance_inventory_file_open:\n            instance_inventory_file_open.write(instance_inventory_content)\n            Log.success(f'Lab inventory file created : {Utils.get_relative_path(instance_inventory_file)}')\n\n    def _create_provisioning_provider_inventory(self):\n        Log.info('Create instance provisioning files')\n        # create provisioning inventory\n        lab_provider_path = GoadPath.get_lab_provider_path(self.lab_name, self.provider_name)\n        environment = Environment(loader=FileSystemLoader(lab_provider_path))\n        # create inventory template\n        inventory_template = environment.get_template(\"inventory\")\n        instance_inventory_content = inventory_template.render(\n            lab_name=self.lab_name,\n            ip_range=self.ip_range,\n            provider_name=self.provider_name\n        )\n        # create instance inventory file\n        instance_inventory_file = self.instance_path + sep + 'inventory'\n        with open(instance_inventory_file, mode=\"w\", encoding=\"utf-8\") as inventory_file:\n            inventory_file.write(instance_inventory_content)\n            Log.success(f'Instance inventory file created : {Utils.get_relative_path(instance_inventory_file)}')\n\n    def _create_extensions_inventory(self):\n        Log.info('Create instance extensions inventory files')\n\n        for extension in self.extensions:\n            extension_folder = GoadPath.get_extension_path(extension)\n            extension_environment = Environment(loader=FileSystemLoader(extension_folder))\n            instance_extension_inventory_template = extension_environment.get_template(\"inventory\")\n            instance_extension_inventory_content = instance_extension_inventory_template.render(\n                lab_name=self.lab_name,\n                ip_range=self.ip_range,\n                provider_name=self.provider_name\n            )\n\n            # create instance extension inventory file\n            instance_extension_inventory_file = self.instance_path + sep + extension + '_inventory'\n            with open(instance_extension_inventory_file, mode=\"w\", encoding=\"utf-8\") as inventory_file:\n                inventory_file.write(instance_extension_inventory_content)\n                Log.success(f'Instance inventory file created : {Utils.get_relative_path(instance_extension_inventory_file)}')\n\n    def update_instance_folder(self):\n        self.create_instance_folder(True)\n\n    def create_instance_folder(self, force=False):\n        instance_exist = False\n        if os.path.isdir(self.instance_path):\n            instance_exist = True\n            if force:\n                Log.info(f'Instance {self.instance_id} already exist override')\n            else:\n                Log.error(f'Instance {self.instance_id} already exist abort')\n                return False\n\n        # create instance dir\n        if not instance_exist:\n            try:\n                os.mkdir(self.instance_path, 0o755)\n            except Exception as e:\n                Log.error('Instance dir creation error')\n                return False\n\n        try:\n            self._create_provider_dir()\n        except ProviderPathNotFound as e:\n            # delete instance\n            self.delete_instance()\n            return False\n\n        self._create_provisioning_lab_inventory('inventory_disable_vagrant')\n        self._create_provisioning_provider_inventory()\n        self._create_extensions_inventory()\n        if self.status is not None and not force:\n            self.status = CREATED\n        self.save_json_instance()\n        Log.info(f'Instance {self.instance_id} created')\n        return True\n\n    def set_status(self, status):\n        self.status = status\n        self.save_json_instance()\n\n    def get_status(self):\n        return self.status\n\n    def delete_instance(self):\n        if not os.path.isdir(self.instance_path):\n            Log.error('Instance does not exist abort')\n            return False\n        Log.info(f'Instance id {self.instance_id} will be deleted.')\n        Log.info(f'Instance folder {self.instance_path} will be deleted.')\n        Log.warning(f'Are you sure ?')\n        if Utils.confirm('(y/N)'):\n            lab_destroyed = self.provider.destroy()\n            if lab_destroyed:\n                shutil.rmtree(self.instance_path, ignore_errors=False, onerror=None)\n                Log.success('instance deleted')\n                return True\n            else:\n                Log.error('Error during lab destruction')\n        return False\n\n    def update_ip_range(self, ip_range):\n        self.ip_range = ip_range\n        self.update_instance_folder()\n"
  },
  {
    "path": "goad/instances.py",
    "content": "import json\nfrom rich.table import Table\nfrom rich import print\nfrom goad.goadpath import *\nfrom goad.log import Log\nfrom goad.instance import LabInstance\n\n\nclass LabInstances:\n\n    def __init__(self, config):\n        self.instances = None\n        self._init_instances(config)\n\n    def _init_instances(self, config):\n        self.instances = {}\n        workspace_path = GoadPath.get_workspace_path()\n        for instance in Utils.list_folders(workspace_path):\n            instance_info_file = workspace_path + sep + instance + sep + 'instance.json'\n            if os.path.isfile(instance_info_file):\n                with open(instance_info_file, 'r') as instance_info_openfile:\n                    # Reading from json file\n                    instance_info = json.load(instance_info_openfile)\n                    lab_name = instance_info['lab']\n                    provider_name = instance_info['provider']\n                    provisioning_method = instance_info['provisioner']\n                    ip_range = instance_info['ip_range']\n                    extensions = instance_info['extensions']\n                    status = instance_info['status']\n                    is_default = instance_info['is_default']\n                    self.instances[instance] = LabInstance(instance, lab_name, config, provider_name, provisioning_method, ip_range, extensions, status, is_default)\n\n    def nb_instances(self):\n        return len(self.instances)\n\n    def add_instance(self, instance):\n        self.instances[instance.instance_id] = instance\n\n    def del_instance(self, instance_id):\n        del self.instances[instance_id]\n\n    def get_instance(self, instance_id):\n        if instance_id in self.instances.keys():\n            return self.instances[instance_id]\n        else:\n            return None\n\n    @staticmethod\n    def color_status(status):\n        if status == CREATED:\n            status = f'[red]{status}[/red]'\n        elif status == PROVIDED:\n            status = f'[yellow]{status}[/yellow]'\n        elif status == READY:\n            status = f'[green]{status}[/green]'\n        return status\n\n    @staticmethod\n    def color_provider(provider):\n        if provider == AWS:\n            provider = f'[orange1]{provider}[/orange1]'\n        elif provider == AZURE:\n            provider = f'[deep_sky_blue1]{provider}[/deep_sky_blue1]'\n        elif provider == VIRTUALBOX:\n            provider = f'[dodger_blue3]{provider}[/dodger_blue3]'\n        elif provider == VMWARE:\n            provider = f'[cyan3]{provider}[/cyan3]'\n        elif provider == VMWARE_ESXI:\n            provider = f'[cyan1]{provider}[/cyan1]'\n        elif provider == PROXMOX:\n            provider = f'[dark_orange3]{provider}[/dark_orange3]'\n        return provider\n\n    def show_instances(self, lab_name='', provider_name='', current_instance_id='', filter_instance_id=''):\n        instance_found = False\n        table = Table()\n        table.add_column('Instance ID')\n        table.add_column('Lab')\n        table.add_column('Provider')\n        table.add_column('IP Range')\n        table.add_column('Status')\n        table.add_column('Is Default')\n        table.add_column('Extensions')\n        for instance_id, instance in self.instances.items():\n            # if filter enabled continue only if instance match the filter\n            if filter_instance_id != '':\n                if instance_id != filter_instance_id:\n                    continue\n\n            if lab_name != '' and lab_name != instance.lab_name:\n                continue\n            if provider_name != '' and provider_name != instance.provider_name:\n                continue\n            instance_found = True\n            table.add_row(f'[red]> [/red][green]{instance_id}[/green]' if instance_id == current_instance_id else instance_id,\n                          instance.lab_name,\n                          self.color_provider(instance.provider_name),\n                          instance.ip_range + '.0/24',\n                          self.color_status(instance.status),\n                          'Yes' if instance.is_default else 'No',\n                          \", \".join(instance.extensions)\n                          )\n        if instance_found:\n            print(table)\n        else:\n            Log.warning('No instance found, change your config and use [italic][blue]install[/blue][/italic] to create a lab instance')\n"
  },
  {
    "path": "goad/jumpbox.py",
    "content": "from goad.command.cmd_factory import CommandFactory\nfrom goad.log import Log\nfrom goad.utils import *\nfrom goad.goadpath import GoadPath\n\n\nclass JumpBox:\n\n    def __init__(self, instance, creation=False):\n        self.lab_name = instance.lab_name\n        self.instance_id = instance.instance_id\n        self.instance_path = instance.instance_path\n        self.provider = instance.provider\n        self.ssh_key = self.get_jumpbox_key(creation)\n        self.username = 'goad'\n        self.command = CommandFactory.get_command()\n\n        if not creation:\n            self.ip = self.provider.get_jumpbox_ip(instance.ip_range)\n            if self.ssh_key is None:\n                Log.error('Missing ssh file JumpBox remote connection')\n            elif os.path.isfile(self.ssh_key) is None:\n                Log.error('Missing ssh file JumpBox remote connection')\n            if self.ip is None:\n                Log.error('Missing ip for JumpBox remote connection')\n        else:\n            self.ip = None\n\n    def provision(self):\n        script_name = self.provider.jumpbox_setup_script\n        script_file = GoadPath.get_script_file(script_name)\n        if not os.path.isfile(script_file):\n            Log.error(f'script file: {script_file} not found !')\n            return None\n        self.run_script(script_file)\n\n    def get_jumpbox_key(self, creation=False):\n        return self.instance_path + os.path.sep + 'ssh_keys' + os.path.sep + 'ubuntu-jumpbox.pem'\n\n    def ssh(self):\n        ssh_cmd = f\"ssh -o StrictHostKeyChecking=no -i {self.ssh_key} {self.username}@{self.ip}\"\n        self.command.run_shell(ssh_cmd, project_path)\n\n    def ssh_proxy(self, port):\n        ssh_cmd = f\"ssh -o StrictHostKeyChecking=no -D {port} -i {self.ssh_key} {self.username}@{self.ip}\"\n        self.command.run_shell(ssh_cmd, project_path)\n\n    def run_script(self, script):\n        ssh_cmd = f'ssh -o StrictHostKeyChecking=no -i {self.ssh_key} {self.username}@{self.ip} \"bash -s\" < {script}'\n        self.command.run_shell(ssh_cmd, project_path)\n\n    def sync_sources(self):\n        \"\"\"\n        rsync ansible folder to the jumpbox ip\n        :return:\n        \"\"\"\n        # # rsync -a --exclude-from='.gitignore' -e \"ssh -o 'StrictHostKeyChecking no' -i $CURRENT_DIR/ad/$lab/providers/$provider/ssh_keys/ubuntu-jumpbox.pem\" \"$CURRENT_DIR/\" goad@$public_ip:~/GOAD/\n        source = GoadPath.get_project_path()\n        if Utils.is_valid_ipv4(self.ip):\n            destination = f'{self.username}@{self.ip}:~/GOAD/'\n            self.command.rsync(source, destination, self.ssh_key)\n\n            # workspace\n            source = self.instance_path\n            destination = f'{self.username}@{self.ip}:~/GOAD/workspace/'\n            self.command.rsync(source, destination, self.ssh_key, False)\n        else:\n            Log.error('Can not sync source jumpbox ip is invalid')\n\n    def run_command(self, command, path):\n        ssh_cmd = f'ssh -t -o StrictHostKeyChecking=no -i {self.ssh_key} {self.username}@{self.ip} \"cd {path} && {command}\"'\n        result = self.command.run_command(ssh_cmd, project_path)\n        return result\n"
  },
  {
    "path": "goad/lab_manager.py",
    "content": "from goad.instances import LabInstances\nfrom goad.instance import LabInstance\nfrom goad.labs import Labs\nfrom goad.provisioner.ansible.ansible import *\nfrom goad.settings import Settings\n\n\nclass LabManager(metaclass=SingletonMeta):\n\n    def __init__(self):\n        self.labs = None\n        self.current_lab = None\n        self.current_provider = None\n        self.current_provisioner = None\n        self.current_extensions = []\n        self.current_ip_range = None\n\n        self.config = None\n        self.lab_instances = None\n        self.current_instance = None\n        self.current_settings = None\n\n    def init(self, config, args):\n        # Prepare all labs objects\n        self.labs = Labs(config)\n        # Prepare all instance objects\n        self.lab_instances = LabInstances(config)\n        # create current settings object\n        self.current_settings = Settings(self)\n        # init lab current config values\n        self.config = config\n        self.current_settings.set_lab_name(self.config.get_value('default', LAB), False)\n        self.current_settings.set_provider_name(self.config.get_value('default', PROVIDER), False)\n        self.current_settings.set_provisioner_name(self.config.get_value('default', PROVISIONER))\n        self.current_settings.set_ip_range(self.config.get_value('default', IP_RANGE))\n        if args.extensions:\n            self.current_settings.set_extensions(args.extensions)\n        return self\n\n    def load_default_instance(self):\n        # load default instance\n        for instance_id, instance in self.lab_instances.instances.items():\n            if instance.is_default:\n                self.load_instance(instance_id)\n                break\n\n    def show_settings(self):\n        Log.success('Current Settings : ')\n        self.current_settings.show()\n        print()\n        Log.success(f'Configuration File content : {GoadPath.get_config_file()} (merged with args for the default section)')\n        self.config.show()\n\n    def inline_settings(self):\n        return self.current_settings.inline()\n\n    def update_instance_files(self, arg=''):\n        if self.current_instance is not None:\n            self.current_instance.update_instance_folder()\n\n    def create_instance(self):\n        instance = LabInstance(None, self.current_settings.lab_name, self.config, self.current_settings.provider_name, self.current_settings.provisioner_name,\n                               self.current_settings.ip_range, extensions=self.current_settings.extensions_name)\n        result = instance.create_instance_folder()\n        if result:\n            self.lab_instances.add_instance(instance)\n            self.load_instance(instance.instance_id, creation=True)\n            self.lab_instances.show_instances(current_instance_id=instance.instance_id, filter_instance_id=instance.instance_id)\n\n            if self.lab_instances.nb_instances() == 1:\n                # only instance, set as default\n                self.set_as_default_instance()\n            return True\n        else:\n            Log.error('Error during creating instance folder')\n            return False\n\n    def load_instance(self, instance_id, creation=False):\n        instance = self.lab_instances.get_instance(instance_id)\n        if instance is not None:\n            loading_result = instance.load(self.labs, creation)\n            if loading_result:\n                # unload previous instance if exist\n                self.current_instance = None\n                # load lab instance change current context\n                self.current_settings.update(instance)\n                # load instance\n                self.current_instance = instance\n                Log.success(f'Instance {instance_id} loaded')\n        else:\n            Log.error('Instance not found in workspace')\n\n    def set_as_default_instance(self):\n        if self.current_instance is not None:\n            for instance_id, instance in self.lab_instances.instances.items():\n                if instance_id == self.current_instance.instance_id:\n                    instance.is_default = True\n                else:\n                    instance.is_default = False\n                instance.save_json_instance()\n        else:\n            Log.error('No instance selected')\n\n    def unload_instance(self):\n        self.current_instance = None\n        self.current_settings.set_extensions([])\n\n    def delete_instance(self):\n        deleted = False\n        if self.current_instance is not None:\n            deleted = self.current_instance.delete_instance()\n            if deleted:\n                self.lab_instances.del_instance(self.current_instance.instance_id)\n                self.unload_instance()\n        return deleted\n\n    def set_lab(self, lab_name):\n        if self.current_instance is None:\n            self.current_settings.set_lab_name(lab_name)\n        else:\n            Log.error(\"Can't change lab if instance is selected\")\n            Log.info('use unload to quit the current instance')\n\n    def set_provider(self, provider_name):\n        if self.current_instance is None:\n            self.current_settings.set_provider_name(provider_name)\n        else:\n            Log.error(\"Can't change provider if instance is selected\")\n            Log.info('use unload to quit the current instance')\n\n    def set_provisioner(self, provisioner_name):\n        self.current_settings.set_provisioner_name(provisioner_name)\n\n    def set_ip_range(self, ip_range):\n        self.current_settings.set_ip_range(ip_range)\n\n    def get_ip_range(self):\n        return self.current_settings.ip_range\n\n    def set_extensions(self, extensions_name):\n        self.current_settings.set_extensions(extensions_name)\n\n    def get_labs(self):\n        return self.labs.get_labs_list()\n\n    def get_lab(self, lab_name):\n        return self.labs.get_lab(lab_name)\n\n    def is_lab_exist(self, lab_name):\n        return self.labs.is_exist(lab_name)\n\n    def get_current_lab_name(self):\n        return self.current_settings.lab_name\n\n    def get_current_provider_name(self):\n        return self.current_settings.provider_name\n\n    def check(self):\n        lab = self.get_lab(self.get_current_lab_name())\n        provider = lab.get_provider(self.get_current_provider_name())\n        if provider is not None:\n            return provider.check()\n        else:\n            Log.error('error provider not found')\n            return False\n\n    # instance function\n    def get_current_instance_id(self):\n        if self.current_instance is not None:\n            return self.current_instance.instance_id\n        return ''\n\n    def get_current_instance(self):\n        return self.current_instance\n\n    def get_current_instance_lab(self):\n        if self.current_instance is None:\n            return None\n        return self.current_instance.lab\n\n    def get_current_instance_provider(self):\n        if self.current_instance:\n            return self.current_instance.provider\n        else:\n            return None\n\n    def get_instance_options(self):\n        return list(self.lab_instances.instances.keys())\n\n    def get_current_instance_provisioner(self):\n        return self.current_instance.provisioner\n\n    def get_labs_options(self):\n        return list(self.labs.labs.keys())\n\n    def get_provider_options(self):\n        lab_name = self.current_settings.lab_name\n        options = []\n        for lab in self.labs.get_labs_list():\n            if lab.lab_name == lab_name:\n                options = list(lab.providers.keys())\n                break\n        return options\n\n    def provisioning_method_options(self):\n        lab_name = self.current_settings.lab_name\n        lab = self.get_lab(lab_name)\n        provider = lab.get_provider(self.current_settings.provider_name)\n        return provider.allowed_provisioners\n"
  },
  {
    "path": "goad/labs.py",
    "content": "from goad.extension import Extension\nfrom goad.provider.provider_factory import ProviderFactory\nfrom goad.utils import *\nfrom goad.goadpath import GoadPath\nfrom goad.log import Log\nfrom goad.exceptions import *\n\n\nclass Labs:\n    def __init__(self, config):\n        self.labs = {}\n        for lab_name in Utils.list_folders(GoadPath.get_labs_path()):\n            if lab_name != 'TEMPLATE':\n                try:\n                    self.labs[lab_name] = Lab(lab_name, config)\n                except ProviderPathNotFound as e:\n                    Log.warning(f'lab {lab_name} not loaded provider path not found')\n\n    def get_lab(self, lab_name):\n        if lab_name not in self.labs.keys():\n            return None\n        return self.labs[lab_name]\n\n    def get_labs_list(self):\n        return list(self.labs.values())\n\n    def is_exist(self, lab_name):\n        return lab_name in self.labs.keys()\n\n\nclass Lab:\n    def __init__(self, lab_name, config):\n        self.lab_name = lab_name\n        self.providers = {}\n        self.extensions = {}\n        try:\n            self._load_providers(lab_name, config)\n        except FileNotFoundError as e:\n            raise ProviderPathNotFound(e)\n        try:\n            self._load_extensions(lab_name)\n        except FileNotFoundError as e:\n            # no extensions\n            pass\n\n    def _load_providers(self, lab_name, config):\n        for provider_name in Utils.list_folders(GoadPath.get_lab_providers_path(lab_name)):\n            provider = ProviderFactory.get_provider(provider_name, lab_name, config)\n            if provider is not None:\n                self.providers[provider_name] = provider\n\n    def _load_extensions(self, lab_name):\n        for extension_name in Utils.list_folders(GoadPath.get_extensions_path()):\n            extension = Extension(extension_name)\n            if extension.is_available(lab_name):\n                self.extensions[extension_name] = extension\n\n    def get_provider(self, provider_name):\n        if provider_name not in self.providers.keys():\n            return None\n        return self.providers[provider_name]\n\n    def get_first_provider_name(self):\n        return next(iter(self.providers))\n\n    def get_extension(self, extension_name):\n        if extension_name in self.extensions.keys():\n            return self.extensions[extension_name]\n        else:\n            return None\n\n    def get_list_extensions_name(self):\n        return list(self.extensions.keys())\n\n    def show_extensions(self):\n        for extension_name in self.extensions.keys():\n            self.extensions[extension_name].show()\n"
  },
  {
    "path": "goad/local_jumpbox.py",
    "content": "import os.path\n\nfrom goad.command.linux import LinuxCommand\nfrom goad.command.wsl import WslCommand\nfrom goad.log import Log\nfrom goad.utils import *\nfrom goad.goadpath import GoadPath\nfrom goad.jumpbox import JumpBox\n\n\nclass LocalJumpBox(JumpBox):\n\n    def __init__(self, instance, creation=False):\n        super().__init__(instance, creation)\n        self.username = 'vagrant'\n\n    def provision(self):\n        script_name = self.provider.jumpbox_setup_script\n        script_file = GoadPath.get_script_file(script_name)\n        if not os.path.isfile(script_file):\n            Log.error(f'script file: {script_file} not found !')\n            return None\n        self.command.scp(script_file, f'{self.username}@{self.ip}:~/setup.sh', self.ssh_key, self.instance_path)\n        if Utils.is_windows():\n            # if is windows convert line ending\n            self.run_command(\"sudo apt update && sudo apt install -y dos2unix\", '~')\n            self.run_command(\"dos2unix setup.sh\", '~')\n        self.run_command('bash setup.sh', '~')\n\n    def get_jumpbox_key(self, creation=False):\n        if not creation:\n            # example : workspace/bf0c11-goad-light-vmware/provider/.vagrant/machines/ELK/vmware_desktop/private_key\n            provider_folder = f'{self.instance_path}/provider/.vagrant/machines/PROVISIONING/'.replace('/', os.path.sep)\n            provider_folders = Utils.list_folders(provider_folder)\n            if len(provider_folders) > 0:\n                return provider_folder + provider_folders[0] + os.path.sep + 'private_key'\n            key_supposed_path = provider_folder + '<provider_name>' + os.path.sep + 'private_key'\n            Log.error(f'PROVISIONING ssh key not found at : {key_supposed_path}')\n        return None\n\n    def sync_sources(self):\n        \"\"\"\n        rsync ansible folder to the jumpbox ip\n        local_vm already got GOAD installed in ~/GOAD so the only thing to sync is the workspace folder\n        :return:\n        \"\"\"\n        if Utils.is_valid_ipv4(self.ip):\n            # Copy the globalsettings.ini file to the jumpbox\n            self.command.scp(GoadPath.get_global_inventory_path(), f'{self.username}@{self.ip}:~/GOAD/globalsettings.ini', self.ssh_key, self.instance_path)\n            # create workspace dir if not exist\n            self.run_command('mkdir -p ~/GOAD/workspace/' + self.instance_id, '~')\n            # workspace inventory files (no need -r as it will copy all the provider folder)\n            for src_file in Utils.list_files(self.instance_path):\n                source = self.instance_path + os.path.sep + src_file\n                destination_file = f'~/GOAD/workspace/{self.instance_id}/{src_file}'\n                destination = f'{self.username}@{self.ip}:{destination_file}'\n                self.command.scp(source, destination, self.ssh_key, self.instance_path)\n                if Utils.is_windows():\n                    # if is windows convert line ending\n                    self.run_command(f\"dos2unix {destination_file}\", '~')\n        else:\n            Log.error('Can not sync source jumpbox ip is invalid')\n"
  },
  {
    "path": "goad/log.py",
    "content": "from rich import print\n\nfrom goad.utils import *\n\nlog_level = INFO\n\n\nclass Log:\n\n    @staticmethod\n    def error(message, level=INFO):\n        if level >= log_level:\n            print(f'[red][-] {message} [/red]')\n\n    @staticmethod\n    def warning(message, level=INFO):\n        if level >= log_level:\n            print(f'[yellow][-] {message} [/yellow]')\n\n    @staticmethod\n    def success(message, level=INFO):\n        if level >= log_level:\n            print(f'[green][+] {message} [/green]')\n\n    @staticmethod\n    def info(message, level=INFO):\n        if level >= log_level:\n            print(f'[cyan][*] [/cyan]{message}')\n\n    @staticmethod\n    def basic(message, level=INFO):\n        if level >= log_level:\n            print(f'{message}')\n\n    @staticmethod\n    def cmd(message, level=INFO):\n        if level >= log_level:\n            print(f'[cyan][*] [/cyan]Running command : [yellow]{message}[/yellow]')\n"
  },
  {
    "path": "goad/menu.py",
    "content": "from rich import print\nfrom goad.utils import *\n\n\ndef print_logo():\n    logo = r\"\"\"[white]\n   _____   _____          _____ \n  / ____| / ||| \\  [blue] /\\\\[/blue]   |  __ \\\n | |  __||  |||  | [blue]/  \\\\[/blue]  | |  | |\n | | |_ ||  |||  |[blue]/ /\\ \\\\[/blue] | |  | |\n | |__| ||  |||  [blue]/ /__\\ \\\\[/blue]| |__| |\n  \\_____| \\_|||_[blue]/________\\\\[/blue]_____/\n    [bold]Game Of Active Directory[/bold]\n      [yellow][italic]Pwning is coming[/italic][/yellow]\n[/white]\nGoad management console type help or ? to list commands\n\"\"\"\n    print(logo)\n\n\ndef print_menu_title(title):\n    print()\n    print(f'[cyan3]*** {title} ***[/cyan3]')\n\n\ndef print_menu_entry(cmd, description):\n    line = f'{cmd} [white]'.ljust(48, '.')\n    print(f'{line}[/white] [sky_blue3]{description}[/sky_blue3]')\n\n\ndef print_menu(lab_manager, advanced=True, debug=False):\n    provider = lab_manager.get_current_provider_name()\n\n    if lab_manager.get_current_instance() is not None:\n        use_jumpbox = lab_manager.get_current_instance_provisioner().use_jumpbox\n        print_menu_title('Manage Lab instance commands')\n        print_menu_entry('status', 'show current status')\n        print_menu_entry('start', 'start lab')\n        print_menu_entry('stop', 'stop lab')\n        print_menu_entry('destroy', 'destroy lab')\n        if lab_manager.get_current_instance().is_vagrant():\n            print_menu_entry('snapshot', 'snapshot lab')\n            print_menu_entry('reset', 'revert lab to last snapshot')\n\n        print_menu_title('Manage one vm commands')\n        print_menu_entry('start_vm <vm_name>', 'start selected virtual machine')\n        print_menu_entry('stop_vm <vm_name>', 'stop selected virtual machine')\n        print_menu_entry('restart_vm <vm_name>', 'restart selected virtual machine')\n        print_menu_entry('destroy_vm <vm_name>', 'destroy selected virtual machine')\n\n        print_menu_title('Extensions')\n        print_menu_entry('list_extensions', 'list extensions')\n        print_menu_entry('install_extension <extension>', 'install extension (providing + provisioning)')\n\n        if advanced:\n            print_menu_entry('provision_extension <extension>', 'provision extension (provisioning only)')\n\n        if use_jumpbox:\n            print_menu_title('JumpBox')\n            if advanced:\n                print_menu_entry('prepare_jumpbox', 'install package on the jumpbox for provisioning')\n                print_menu_entry('sync_source_jumpbox', 'sync source of the jumpbox')\n            print_menu_entry('ssh_jumpbox', 'connect to jump box with ssh')\n            print_menu_entry('ssh_jumpbox_proxy <proxy_port>', 'connect to jump box with ssh and start a socks proxy')\n\n        if advanced:\n            print_menu_title('Providing (Vagrant/Terrafom)')\n            print_menu_entry('provide', 'run only the providing (vagrant/terraform)')\n\n            print_menu_title('Provisioning (Ansible)')\n            print_menu_entry('provision <playbook>', 'run specific ansible playbook')\n            print_menu_entry('provision_lab', 'run all the current lab ansible playbooks')\n            print_menu_entry('provision_lab_from <playbook>', 'run all the current lab ansible playbooks from specific playbook to the end')\n\n    print_menu_title('Lab Instances')\n    print_menu_entry('check', 'check dependencies before creation')\n    if lab_manager.get_current_instance() is None:\n        print_menu_entry('install / create', 'install the selected lab and create a lab instance')\n        print_menu_entry('create_empty', 'prepare a lab instance folder without providing and provisioning')\n    if lab_manager.get_current_instance() is not None:\n        print_menu_entry('install', 'install the current instance (provide + prepare_jumpbox + provision_lab')\n        print_menu_entry('set_as_default', 'set instance as default')\n        print_menu_entry('update_instance_files', 'update lab instance files')\n        if provider != AZURE and provider != AWS:\n            print_menu_entry('disable_vagrant', 'disable vagrant user')\n            print_menu_entry('enable_vagrant', 'enable vagrant user')\n    print_menu_entry('list', 'list lab instances')\n    print_menu_entry('load <instance_id>', 'load a lab instance')\n\n    print_menu_title('Configuration')\n    print_menu_entry('config', 'show current configuration')\n    if lab_manager.get_current_instance() is None:\n        print_menu_entry('labs', 'show all labs and available providers')\n        print_menu_entry('set_lab <lab>', 'set the lab to use')\n        print_menu_entry('set_provider <provider>', 'set the provider to use')\n        print_menu_entry('set_provisioning_method <method>', 'set the provisioning method')\n        print_menu_entry('set_ip_range <range>', 'set the 3 first digit of the ip to use (ex: 192.168.56)')\n\n    if lab_manager.get_current_instance() is not None:\n        print_menu_entry('unload', 'unload current instance')\n        print_menu_entry('delete', 'delete the currently selected lab instance')\n"
  },
  {
    "path": "goad/provider/ludus/ludus.py",
    "content": "from goad.provider.provider import Provider\nfrom goad.command.cmd_factory import CommandFactory\nfrom goad.utils import *\nfrom goad.log import Log\nimport json\nimport time\n\n\ndef _get_ludus_major_version(config):\n    \"\"\"Run `ludus version` and return the major version number (1 or 2).\n\n    Falls back to the LUDUS_VERSION env var, then defaults to 1.\n    \"\"\"\n    if 'LUDUS_VERSION' in os.environ:\n        return int(os.environ['LUDUS_VERSION'])\n    api_key = config.get_value('ludus', 'ludus_api_key', 'not_set')\n    command = CommandFactory.get_command()\n    if command.on_ludus():\n        output = command.run_ludus_result(['version', '--json'], None, api_key, do_log=False)\n        if not output:\n            return 1\n        try:\n            version_json = json.loads(output)\n            version = version_json.get('version', '')\n            if version:\n                return int(version.split('.')[0])\n        except (json.JSONDecodeError, KeyError, ValueError):\n            pass\n    return 1\n\n\nclass LudusProvider(Provider):\n    provider_name = LUDUS\n    default_provisioner = PROVISIONING_LOCAL\n    allowed_provisioners = [PROVISIONING_LOCAL, PROVISIONING_RUNNER]\n    update_ip_range = True\n\n    def __init__(self, lab_name, config):\n        super().__init__(lab_name)\n        self.api_key = config.get_value('ludus', 'ludus_api_key', 'not_set')\n        self.use_impersonation = config.get_value('ludus', 'use_impersonation', 'no') == 'yes'\n        self.lab_user = 'GOAD'\n        self.major_version = _get_ludus_major_version(config)\n\n    def _user_command(self, args):\n        \"\"\"Build a user-related command list, adding the v1 URL prefix when needed.\"\"\"\n        if self.major_version < 2:\n            return ['--url', 'https://127.0.0.1:8081'] + args\n        return args\n\n    def set_lab_user(self, lab_user):\n        if self.use_impersonation:\n            self.lab_user = lab_user\n\n    def get_ludus_user(self):\n        ludus_user = None\n        ludus_version = self.command.run_ludus_result([\"version\"], self.path, self.api_key)\n        if ludus_version is None:\n            Log.error('Error to contact ludus.')\n            return None\n        if 'No API key loaded' in ludus_version:\n            Log.error('Please add the ludus api key to HOME/.goad/goad.ini file')\n        else:\n            Log.success('Api key is set')\n            if self.use_impersonation:\n                command = self._user_command(['user', 'list', '--json'])\n                ludus_users = self.command.run_ludus_result(command, self.path, self.api_key)\n                print(ludus_users)\n                users = json.loads(ludus_users)\n                if len(users) > 0:\n                    Log.info(f'Current user name : {users[0][\"name\"]}')\n                    Log.info(f'Current user ID   : {users[0][\"userID\"]}')\n                    Log.info(f'User is admin     : {users[0][\"isAdmin\"]}')\n                    if not users[0][\"isAdmin\"]:\n                        Log.error('User must be admin')\n                    else:\n                        ludus_user = users[0][\"userID\"]\n            else:\n                ludus_user = 'ok'\n        return ludus_user\n\n    def check(self):\n        Log.info(f\"Using Ludus {self.major_version} provider\")\n        check = super().check()\n        check_ludus = self.command.check_ludus()\n        if check_ludus:\n            current_ludus_user = self.get_ludus_user()\n            if current_ludus_user is not None:\n                check_ludus = True\n\n        checks = [\n            self.command.check_disk(),\n            self.command.check_ram(),\n            self.command.check_ansible()\n        ]\n        return check and check_ludus and all(checks)\n\n    def user_exist(self, user_to_test):\n        user_exist = False\n        command = self._user_command(['user', 'list', 'all', '--json'])\n        ludus_users = self.command.run_ludus_result(command, self.path, self.api_key)\n        users = json.loads(ludus_users)\n        for user in users:\n            if user['userID'] == user_to_test:\n                Log.success(f'User {user_to_test} already exist')\n                user_exist = True\n                break\n        return user_exist\n\n    def _create_user(self):\n        \"\"\"Create the lab user via the ludus CLI.\"\"\"\n        if self.major_version >= 2:\n            password = ''.join(random.choices(string.ascii_letters + string.digits, k=12))\n            command = self._user_command([\n                'user', 'add', '-n', self.lab_user, '-i', self.lab_user,\n                '-e', f'{self.lab_user}@ludus.internal', '-p', password,\n            ])\n        else:\n            command = self._user_command([\n                'user', 'add', '-n', self.lab_user, '-i', self.lab_user,\n            ])\n        self.command.run_ludus_result(command, self.path, self.api_key)\n        Log.info('Lab user created')\n\n    def _grant_access(self, current_ludus_user):\n        \"\"\"Grant the admin user access to the lab range after deployment.\"\"\"\n        Log.info(f'Add access to lab range {self.lab_user} for your user {current_ludus_user}')\n        if self.major_version >= 2:\n            self.command.run_ludus(\n                f'range assign {current_ludus_user} {self.lab_user}',\n                self.path, self.api_key,\n            )\n        else:\n            self.command.run_ludus(\n                f'range access grant --target {self.lab_user} --source {current_ludus_user}',\n                self.path, self.api_key,\n            )\n\n    def install(self):\n        current_ludus_user = ''\n        if self.use_impersonation:\n            current_ludus_user = self.get_ludus_user()\n            if current_ludus_user is None:\n                return False\n\n            if not self.user_exist(self.lab_user):\n                Log.info('Lab user does not exist create it')\n                self._create_user()\n\n            if not self.user_exist(self.lab_user):\n                Log.error('Lab user creation error')\n                return False\n\n        set_config_result = self.command.run_ludus(\n            f'range config set -f config.yml', self.path, self.api_key,\n            self.lab_user, self.use_impersonation,\n        )\n        if not set_config_result:\n            return False\n\n        deploy_result = self.command.run_ludus(\n            f'range deploy', self.path, self.api_key,\n            self.lab_user, self.use_impersonation,\n        )\n        if not deploy_result:\n            return False\n\n        while True:\n            command = ['range', 'status', '--json']\n            ludus_status = self.command.run_ludus_result(\n                command, self.path, self.api_key,\n                do_log=False, user_id=self.lab_user, impersonation=self.use_impersonation,\n            )\n            if ludus_status is None:\n                return False\n            try:\n                range_status = json.loads(ludus_status)\n                range_state = range_status['rangeState']\n                if range_state == 'ERROR':\n                    Log.error('Error during deployment')\n                    self.command.run_ludus(\n                        'range errors', self.path, self.api_key,\n                        self.lab_user, self.use_impersonation,\n                    )\n                    return False\n                elif range_state == 'DEPLOYING':\n                    Log.info('deploying...be patient')\n                elif range_state == 'SUCCESS':\n                    range_number = range_status['rangeNumber']\n                    Log.info(f'deployment finished, range number : {range_number}')\n                    break\n                else:\n                    Log.warning(f'Unknow status : {range_state}')\n            except Exception as e:\n                Log.error('')\n                return False\n            time.sleep(30)\n\n        if self.use_impersonation:\n            self._grant_access(current_ludus_user)\n        return True\n\n    def get_ip_range(self):\n        try:\n            command = ['range', 'status', '--json']\n            ludus_status = self.command.run_ludus_result(\n                command, self.path, self.api_key,\n                do_log=True, user_id=self.lab_user, impersonation=self.use_impersonation,\n            )\n            range_status = json.loads(ludus_status)\n            range_number = range_status['rangeNumber']\n            Log.info(f'Ludus ip range : {range_number}')\n            return f'10.{range_number}.10'\n        except Exception as e:\n            Log.error('Error during ludus status')\n            return None\n\n    def destroy(self):\n        return self.command.run_ludus(\n            f'range rm', self.path, self.api_key,\n            self.lab_user, self.use_impersonation,\n        )\n\n    def start(self):\n        return self.command.run_ludus(\n            f'power on -n all', self.path, self.api_key,\n            self.lab_user, self.use_impersonation,\n        )\n\n    def stop(self):\n        return self.command.run_ludus(\n            f'power off -n all', self.path, self.api_key,\n            self.lab_user, self.use_impersonation,\n        )\n\n    def status(self):\n        return self.command.run_ludus(\n            f'range status', self.path, self.api_key,\n            self.lab_user, self.use_impersonation,\n        )\n\n    def destroy_vm(self, vm_name):\n        if self.major_version < 2:\n            Log.error('Not implemented for Ludus v1')\n            return False\n        status = self.command.run_ludus(\n            f'range status --json', self.path, self.api_key,\n            self.lab_user, self.use_impersonation,\n        )\n        if status is None:\n            return False\n        status_json = json.loads(status)\n        for vm in status_json['VMs']:\n            if vm['name'] == vm_name:\n                vm_id = vm['proxmoxID']\n                break\n        return self.command.run_ludus(\n            f'vm destroy {vm_id} --no-prompt', self.path, self.api_key,\n            self.lab_user, self.use_impersonation,\n        )\n\n    def start_vm(self, vm_name):\n        return self.command.run_ludus(\n            f'power on -n {vm_name}', self.path, self.api_key,\n            self.lab_user, self.use_impersonation,\n        )\n\n    def stop_vm(self, vm_name):\n        return self.command.run_ludus(\n            f'power off -n {vm_name}', self.path, self.api_key,\n            self.lab_user, self.use_impersonation,\n        )\n"
  },
  {
    "path": "goad/provider/provider.py",
    "content": "from abc import ABC\nfrom goad.command.cmd_factory import CommandFactory\nfrom goad.utils import *\n\n\nclass Provider(ABC):\n    lab_name = ''\n    provider_name = None\n    default_provisioner = PROVISIONING_LOCAL\n    allowed_provisioners = ALLOWED_PROVISIONER\n    update_ip_range = False\n\n    def __init__(self, lab_name):\n        self.lab_name = lab_name\n        self.path = None\n        self.command = CommandFactory.get_command()\n\n    def set_instance_path(self, provider_instance_path):\n        self.path = provider_instance_path\n\n    def check(self):\n        pass\n\n    def install(self):\n        pass\n\n    def destroy(self):\n        pass\n\n    def start(self):\n        pass\n\n    def stop(self):\n        pass\n\n    def status(self):\n        pass\n\n    def start_vm(self, vm_name):\n        pass\n\n    def stop_vm(self, vm_name):\n        pass\n\n    def destroy_vm(self, vm_name):\n        pass\n\n    def get_jumpbox_ip(self, ip_range=''):\n        return None\n\n    def restart_vm(self, vm_name):\n        self.stop_vm(vm_name)\n        self.start_vm(vm_name)\n"
  },
  {
    "path": "goad/provider/provider_factory.py",
    "content": "from goad.utils import *\nfrom goad.dependencies import Dependencies\n\nif Dependencies.vmware_enabled:\n    from goad.provider.vagrant.vmware import VmwareProvider\nif Dependencies.vmware_esxi_enabled:\n    from goad.provider.vagrant.vmware_esxi import VmwareEsxiProvider\nif Dependencies.virtualbox_enabled:\n    from goad.provider.vagrant.virtualbox import VirtualboxProvider\nif Dependencies.azure_enabled:\n    from goad.provider.terraform.azure import AzureProvider\nif Dependencies.aws_enabled:\n    from goad.provider.terraform.aws import AwsProvider\nif Dependencies.proxmox_enabled:\n    from goad.provider.terraform.proxmox import ProxmoxProvider\nif Dependencies.ludus_enabled:\n    from goad.provider.ludus.ludus import LudusProvider\n\n\nclass ProviderFactory:\n\n    @staticmethod\n    def get_provider(provider_name, lab_name, config):\n        provider = None\n        if provider_name == VIRTUALBOX and Dependencies.virtualbox_enabled:\n            provider = VirtualboxProvider(lab_name)\n        elif provider_name == VMWARE and Dependencies.vmware_enabled:\n            provider = VmwareProvider(lab_name)\n        elif provider_name == VMWARE_ESXI and Dependencies.vmware_esxi_enabled:\n            provider = VmwareEsxiProvider(lab_name)\n        elif provider_name == PROXMOX and Dependencies.proxmox_enabled:\n            provider = ProxmoxProvider(lab_name, config)\n        elif provider_name == AZURE and Dependencies.azure_enabled:\n            provider = AzureProvider(lab_name)\n        elif provider_name == AWS and Dependencies.aws_enabled:\n            provider = AwsProvider(lab_name, config)\n        elif provider_name == LUDUS and Dependencies.ludus_enabled:\n            provider = LudusProvider(lab_name, config)\n        return provider\n"
  },
  {
    "path": "goad/provider/terraform/aws.py",
    "content": "from goad.provider.terraform.terraform import TerraformProvider\nfrom goad.utils import *\nfrom goad.log import Log\n# AWS\nimport boto3\nfrom botocore.exceptions import NoCredentialsError, PartialCredentialsError\n# rich\nfrom rich.table import Table\nfrom rich import print\n\n\nclass AwsProvider(TerraformProvider):\n    provider_name = AWS\n    default_provisioner = PROVISIONING_REMOTE\n    allowed_provisioners = [PROVISIONING_REMOTE]\n\n    def __init__(self, lab_name, config):\n        super().__init__(lab_name)\n        self.jumpbox_setup_script = 'setup_aws.sh'\n        self.tag = lab_name\n        self.aws_region = config.get_value('aws', 'aws_region', 'eu-west-3')\n        self.aws_zone = config.get_value('aws', 'aws_zone', 'eu-west-3c')\n        self.profile_name = 'goad'\n\n    def set_tag(self, tag):\n        # tag should be <instance_id>-<LAB>\n        self.tag = tag\n\n    @staticmethod\n    def _color_vm_state(state):\n        if state == \"running\":\n            return f'[green]{state}[/green]'\n        elif state == \"stopped\":\n            return f'[red]{state}[/red]'\n        return f'[yellow]{state}[/yellow]'\n\n    def check(self):\n        # check terraform bin\n        check = super().check()\n        check_aws = self.command.check_aws()\n        check = check and check_aws\n\n        try:\n            session = boto3.Session(profile_name=self.profile_name)\n            # Create an STS client using the session\n            sts = session.client('sts')\n            # Get the identity of the caller\n            response = sts.get_caller_identity()\n            # Print the user information\n            Log.success(f\"Connected to AWS using profile '{self.profile_name}'\")\n            Log.info(\"User Information:\")\n            Log.info(f\"  Account: {response['Account']}\")\n            Log.info(f\"  User ARN: {response['Arn']}\")\n            Log.info(f\"  User ID: {response['UserId']}\")\n            check = check and True\n        except NoCredentialsError:\n            Log.error(\"Credentials not available.\")\n            check = False\n        except PartialCredentialsError:\n            Log.error(\"Incomplete credentials provided.\")\n            check = False\n        except Exception as e:\n            Log.error(f\"An error occurred: {e}\")\n            check = False\n        return check\n\n    def status(self):\n        session = boto3.Session(profile_name=self.profile_name)\n        ec2_client = session.client('ec2', self.aws_region)\n        aws_ec2 = ec2_client.describe_instances()\n        table = Table()\n        table.add_column('VM Id')\n        table.add_column('Name')\n        table.add_column('Location')\n        table.add_column('PowerState')\n        table.add_column('PublicIP')\n        table.add_column('PrivateIP')\n        for reservation in aws_ec2[\"Reservations\"]:\n            for vm_instance in reservation[\"Instances\"]:\n                vm_id = vm_instance[\"InstanceId\"]\n                vm_name = ''\n                vm_location = self.aws_zone\n                vm_state = self._color_vm_state(vm_instance[\"State\"][\"Name\"])\n                vm_public_ip = ''\n                vm_private_ip = ''\n                vm_lab = ''\n                if \"Tags\" in vm_instance:\n                    for tag in vm_instance[\"Tags\"]:\n                        if tag['Key'] == \"Name\":\n                            vm_name = tag[\"Value\"]\n                        if tag['Key'] == \"Lab\":\n                            vm_lab = tag[\"Value\"]\n                if \"PublicIpAddress\" in vm_instance:\n                    vm_public_ip = vm_instance[\"PublicIpAddress\"]\n                if \"PrivateIpAddress\" in vm_instance:\n                    vm_private_ip = vm_instance[\"PrivateIpAddress\"]\n                if vm_lab != '' and vm_lab == self.tag:\n                    table.add_row(vm_id, vm_name, vm_location, vm_state, vm_public_ip, vm_private_ip)\n\n        print(table)\n\n    def _get_vm_instance_id_list(self, ec2_client):\n        aws_ec2 = ec2_client.describe_instances()\n        instances_ids = []\n        for reservation in aws_ec2[\"Reservations\"]:\n            for vm_instance in reservation[\"Instances\"]:\n                if \"Tags\" in vm_instance:\n                    for tag in vm_instance[\"Tags\"]:\n                        if tag['Key'] == \"Lab\":\n                            vm_lab = tag[\"Value\"]\n                            if vm_lab != '' and vm_lab == self.tag:\n                                instances_ids.append(vm_instance[\"InstanceId\"])\n        return instances_ids\n\n    def start(self):\n        session = boto3.Session(profile_name=self.profile_name)\n        ec2_client = session.client('ec2', self.aws_region)\n        instances_ids = self._get_vm_instance_id_list(ec2_client)\n        ec2_client.start_instances(InstanceIds=instances_ids)\n        Log.info('lab start in progres')\n\n    def stop(self):\n        session = boto3.Session(profile_name=self.profile_name)\n        ec2_client = session.client('ec2', self.aws_region)\n        instances_ids = self._get_vm_instance_id_list(ec2_client)\n        ec2_client.stop_instances(InstanceIds=instances_ids)\n        Log.info('lab stop in progres')\n\n    def start_vm(self, vm_id):\n        session = boto3.Session(profile_name=self.profile_name)\n        ec2_client = session.client('ec2', self.aws_region)\n        instances_ids = self._get_vm_instance_id_list(ec2_client)\n        found = False\n        for instances_id in instances_ids:\n            if instances_id == vm_id:\n                found = True\n                ec2_client.start_instances(InstanceIds=[instances_id])\n\n        if found:\n            Log.info(f'lab vm {vm_id} start in progres')\n        else:\n            Log.error(f'vm id {vm_id} not found, be sure to use the instance_id and not the name for aws')\n        return found\n\n    def stop_vm(self, vm_id):\n        session = boto3.Session(profile_name=self.profile_name)\n        ec2_client = session.client('ec2', self.aws_region)\n        instances_ids = self._get_vm_instance_id_list(ec2_client)\n        found = False\n        for instances_id in instances_ids:\n            if instances_id == vm_id:\n                found = True\n                ec2_client.stop_instances(InstanceIds=[instances_id])\n        if found:\n            Log.info(f'lab vm {vm_id} stop in progres')\n        else:\n            Log.error(f'vm id {vm_id} not found, be sure to use the instance_id and not the name for aws')\n        return found\n\n    def destroy_vm(self, vm_id):\n        session = boto3.Session(profile_name=self.profile_name)\n        ec2_client = session.client('ec2', self.aws_region)\n        instances_ids = self._get_vm_instance_id_list(ec2_client)\n        found = False\n        for instances_id in instances_ids:\n            if instances_id == vm_id:\n                found = True\n                ec2_client.terminate_instances(InstanceIds=[instances_id])\n        if found:\n            Log.info(f'lab vm {vm_id} terminate in progres')\n        else:\n            Log.error(f'vm id {vm_id} not found, be sure to use the instance_id and not the name for aws')\n        return found\n\n    def get_jumpbox_ip(self, ip_range=''):\n        jumpbox_ip = self.command.run_terraform_output(['ubuntu-jumpbox-ip'], self.path)\n        if jumpbox_ip is None:\n            Log.error('Jump box ip not found')\n            return None\n        if not Utils.is_valid_ipv4(jumpbox_ip):\n            Log.error('Invalid IP')\n            return None\n        return jumpbox_ip\n"
  },
  {
    "path": "goad/provider/terraform/azure.py",
    "content": "import json\nfrom goad.log import Log\nfrom goad.provider.terraform.terraform import TerraformProvider\nfrom goad.utils import *\nfrom rich.table import Table\nfrom goad.exceptions import *\nfrom rich import print\nfrom azure.identity import DefaultAzureCredential\nfrom azure.core.exceptions import ClientAuthenticationError\nfrom azure.mgmt.compute import ComputeManagementClient\nfrom azure.mgmt.network import NetworkManagementClient\n\n\nclass AzureProvider(TerraformProvider):\n    provider_name = AZURE\n    default_provisioner = PROVISIONING_REMOTE\n    allowed_provisioners = [PROVISIONING_REMOTE]\n\n    def __init__(self, lab_name):\n        super().__init__(lab_name)\n        self.resource_group = lab_name\n        self.jumpbox_setup_script = 'setup_azure.sh'\n\n    def set_resource_group(self, resource_group):\n        self.resource_group = resource_group\n\n    def _get_subscription_id(self):\n        credential = DefaultAzureCredential()\n        if credential is not None:\n            # find default subscription with subprocess (python sdk doesn't show it)\n            az_accounts = self.command.get_azure_account_output()\n            if az_accounts is not None:\n                subscriptions = json.loads(az_accounts)\n                for subscription in subscriptions:\n                    if subscription.get(\"isDefault\"):\n                        return subscription.get(\"id\")\n        return None\n\n    def check(self):\n        # check terraform bin\n        check = super().check()\n        check_az = self.command.check_azure()\n        check = check and check_az\n        # check azure login\n        try:\n            credential = DefaultAzureCredential()\n            if credential is not None:\n                Log.success(f'Azure authentication ok')\n\n                # find default subscription with subprocess (python sdk doesn't show it)\n                az_accounts = self.command.get_azure_account_output()\n                if az_accounts is not None:\n                    subscriptions = json.loads(az_accounts)\n                    for subscription in subscriptions:\n                        if subscription.get(\"isDefault\"):\n                            Log.info(f'Subscription name : {subscription.get(\"name\")}')\n                            Log.info(f'Subscription id : {subscription.get(\"id\")}')\n                            Log.info(f'Tenant ID : {subscription.get(\"tenantId\")}')\n                            Log.info(f'State : {subscription.get(\"state\")}')\n                            Log.info('If you want to change subscription use: az account set --subscription \"<subscription id>\" ')\n                            check = check and True\n        except ClientAuthenticationError as error:\n            Log.error(f'Azure authentication error : {error.message}')\n            Log.info('Please login before launching the app with \"az login\"')\n            check = False\n        except Exception as error:\n            Log.error(f'Exception during the azure check : {error.message}')\n            check = False\n        return check\n\n    def _auth(self):\n        # Initialize DefaultAzureCredential\n        credential = DefaultAzureCredential()\n        if credential is None:\n            raise AuthenticationFailed('Azure authentication ko')\n        subscription_id = self._get_subscription_id()\n        if subscription_id is None:\n            raise AuthenticationFailed('Subscription ID not found')\n        return credential, subscription_id\n\n    def status(self):\n        try:\n            credential, subscription_id = self._auth()\n        except AuthenticationFailed as e:\n            Log.error(e)\n            return False\n\n        try:\n            # get VMS status\n            # Initialize the ComputeManagementClient with the credential\n            compute_client = ComputeManagementClient(credential, subscription_id)\n            network_client = NetworkManagementClient(credential, subscription_id)\n\n            # List all VMs in the specified resource group\n            vms = compute_client.virtual_machines.list(self.resource_group)\n            Log.info(f\"Azure VMs for resource {self.resource_group}\")\n            table = Table()\n            table.add_column('VM Id')\n            table.add_column('Name')\n            table.add_column('Location')\n            table.add_column('PowerState')\n            table.add_column('PublicIP')\n            table.add_column('PrivateIP')\n\n            # Fetch details of each VM\n            vm_details = []\n            for vm in vms:\n                # IPs\n                vm_public_ips = []\n                vm_private_ips = []\n                for interface in vm.network_profile.network_interfaces:\n                    nic_name = \" \".join(interface.id.split('/')[-1:])\n                    nic_resource_group = \"\".join(interface.id.split('/')[4])\n                    for ip in network_client.network_interfaces.get(nic_resource_group, nic_name).ip_configurations:\n                        if ip.private_ip_address is not None:\n                            vm_private_ips.append(ip.private_ip_address)\n                        if ip.public_ip_address is not None:\n                            public_ip_name = ip.public_ip_address.id.split('/')[-1]\n                            # Get public IP address details\n                            public_ip = network_client.public_ip_addresses.get(nic_resource_group, public_ip_name)\n                            vm_public_ips.append(public_ip.ip_address)\n\n                # powerstate\n                instance_view = compute_client.virtual_machines.instance_view(self.resource_group, vm.name)\n\n                power_state = next((status.code for status in instance_view.statuses if status.code.startswith('PowerState/')), 'Unknown')\n                if power_state.startswith('PowerState/'):\n                    power_state = power_state.split(\"PowerState/\", 1)[1]\n\n                if 'running' in power_state:\n                    power_state = f'[green]{power_state}[/green]'\n                elif 'Unknown' in power_state:\n                    power_state = f'[yellow]{power_state}[/yellow]'\n                else:\n                    power_state = f'[red]{power_state}[/red]'\n                # Append the VM details to the list\n                table.add_row(vm.vm_id, vm.name, vm.location, power_state, ','.join(vm_public_ips), ','.join(vm_private_ips))\n            print(table)\n        except Exception as e:\n            Log.error('Error retreiving running vms')\n            return False\n\n    def start(self):\n        try:\n            credential, subscription_id = self._auth()\n        except AuthenticationFailed as e:\n            Log.error(e)\n            return False\n        try:\n            # Initialize the ComputeManagementClient with the credential\n            compute_client = ComputeManagementClient(credential, subscription_id)\n            Log.info('Start the lab  vms')\n            # List all VMs in the specified resource group\n            for vm in compute_client.virtual_machines.list(self.resource_group):\n                async_vm_stop = compute_client.virtual_machines.begin_start(self.resource_group, vm.name)\n                async_vm_stop.wait()\n                Log.success(f'vm {vm.name} started')\n            self.status()\n        except Exception as e:\n            Log.error('Error starting the vms')\n            return False\n\n    def stop(self):\n        try:\n            credential, subscription_id = self._auth()\n        except AuthenticationFailed as e:\n            Log.error(e)\n            return False\n        try:\n            # Initialize the ComputeManagementClient with the credential\n            compute_client = ComputeManagementClient(credential, subscription_id)\n            Log.info('Stopping the lab vms')\n            # List all VMs in the specified resource group\n            for vm in compute_client.virtual_machines.list(self.resource_group):\n                async_vm_stop = compute_client.virtual_machines.begin_deallocate(self.resource_group, vm.name)\n                async_vm_stop.wait()\n                Log.success(f'vm {vm.name} deallocate (no more billed)')\n            self.status()\n        except Exception as e:\n            Log.error('Error stoping the lab vms')\n            return False\n\n    def start_vm(self, vm_name):\n        try:\n            credential, subscription_id = self._auth()\n        except AuthenticationFailed as e:\n            Log.error(e)\n            return False\n        try:\n            # Initialize the ComputeManagementClient with the credential\n            compute_client = ComputeManagementClient(credential, subscription_id)\n            Log.info(f'Start vm {vm_name}')\n            found = False\n            # List all VMs in the specified resource group\n            for vm in compute_client.virtual_machines.list(self.resource_group):\n                if vm_name == vm.name:\n                    found = True\n                    async_vm_stop = compute_client.virtual_machines.begin_start(self.resource_group, vm.name)\n                    async_vm_stop.wait()\n                    Log.success(f'vm {vm.name} started')\n        except Exception as e:\n            Log.error(f'Error starting vm {vm_name}')\n            return False\n        if not found:\n            Log.error('vm not found')\n        return found\n\n    def stop_vm(self, vm_name):\n        try:\n            credential, subscription_id = self._auth()\n        except AuthenticationFailed as e:\n            Log.error(e)\n            return False\n        try:\n            # Initialize the ComputeManagementClient with the credential\n            compute_client = ComputeManagementClient(credential, subscription_id)\n            Log.info(f'Stopping vm {vm_name}')\n            found = False\n            # List all VMs in the specified resource group\n            for vm in compute_client.virtual_machines.list(self.resource_group):\n                if vm_name == vm.name:\n                    found = True\n                    async_vm_stop = compute_client.virtual_machines.begin_power_off(self.resource_group, vm.name)\n                    async_vm_stop.wait()\n                    Log.success(f'vm {vm.name} power off (still billed)')\n        except Exception as e:\n            Log.error(f'Error stopping vm {vm_name}')\n            return False\n        if not found:\n            Log.error('vm not found')\n        return found\n\n    def destroy_vm(self, vm_name):\n        try:\n            credential, subscription_id = self._auth()\n        except AuthenticationFailed as e:\n            Log.error(e)\n            return False\n        try:\n            # Initialize the ComputeManagementClient with the credential\n            compute_client = ComputeManagementClient(credential, subscription_id)\n            Log.info(f'Deleting vm {vm_name}')\n            found = False\n            # List all VMs in the specified resource group\n            for vm in compute_client.virtual_machines.list(self.resource_group):\n                if vm_name == vm.name:\n                    found = True\n                    async_vm_destroy = compute_client.virtual_machines.begin_delete(self.resource_group, vm.name)\n                    async_vm_destroy.wait()\n                    Log.success(f'vm {vm.name} deleted')\n        except Exception as e:\n            Log.error(f'Error deleting vm {vm_name}')\n            return False\n        if not found:\n            Log.error('vm not found')\n        return found\n\n    def _get_az_jumpbox_ip(self):\n        try:\n            credential, subscription_id = self._auth()\n        except AuthenticationFailed as e:\n            Log.error(e)\n            return None\n        # get VMS status\n        # Initialize the ComputeManagementClient with the credential\n        try:\n            compute_client = ComputeManagementClient(credential, subscription_id)\n            network_client = NetworkManagementClient(credential, subscription_id)\n\n            # List all VMs in the specified resource group\n            vms = compute_client.virtual_machines.list(self.resource_group)\n            # Fetch details of each VM\n            vm_details = []\n            for vm in vms:\n                if 'ubuntu-jumpbox' in vm.name:\n                    # IPs\n                    vm_public_ips = []\n                    for interface in vm.network_profile.network_interfaces:\n                        nic_name = \" \".join(interface.id.split('/')[-1:])\n                        nic_resource_group = \"\".join(interface.id.split('/')[4])\n                        for ip in network_client.network_interfaces.get(nic_resource_group, nic_name).ip_configurations:\n                            if ip.public_ip_address is not None:\n                                public_ip_name = ip.public_ip_address.id.split('/')[-1]\n                                # Get public IP address details\n                                public_ip = network_client.public_ip_addresses.get(nic_resource_group, public_ip_name)\n                                return public_ip.ip_address\n        except Exception as e:\n            Log.error('Error retreiving jumpbox ip')\n            return False\n        return None\n\n    def get_jumpbox_ip(self, ip_range=''):\n        jumpbox_ip = self.command.run_terraform_output(['ubuntu-jumpbox-ip'], self.path)\n        if jumpbox_ip is None:\n            Log.error('Jump box ip not found')\n            return None\n        if not Utils.is_valid_ipv4(jumpbox_ip):\n            Log.error('Invalid IP')\n            return None\n        return jumpbox_ip\n"
  },
  {
    "path": "goad/provider/terraform/proxmox.py",
    "content": "from goad.provider.terraform.terraform import TerraformProvider\nfrom goad.utils import *\nfrom urllib.parse import urlparse\nfrom goad.log import Log\n\nfrom proxmoxer import ProxmoxAPI\nimport getpass\nfrom rich.table import Table\nfrom rich import print\n\n\nclass ProxmoxProvider(TerraformProvider):\n    provider_name = PROXMOX\n    default_provisioner = PROVISIONING_LOCAL\n    allowed_provisioners =  [PROVISIONING_LOCAL, PROVISIONING_RUNNER]\n\n    def __init__(self, lab_name, config):\n        super().__init__(lab_name)\n        self.pm_api_url = config.get_value('proxmox', 'pm_api_url')\n        self.pm_user = config.get_value('proxmox', 'pm_user')\n        self.pm_node = config.get_value('proxmox', 'pm_node')\n        self.pm_pool = config.get_value('proxmox', 'pm_pool')\n        self.pm_password = config.get_value('proxmox', 'pm_pass', None)\n\n    def _get_proxmox(self):\n        if self.pm_password is None:\n            pm_password = getpass.getpass(f\"Enter {self.pm_user} password : \")\n        else:\n            pm_password = self.pm_password\n        parsed_url = urlparse(self.pm_api_url)\n        proxmox = ProxmoxAPI(parsed_url.hostname, user=self.pm_user, password=pm_password, verify_ssl=False)\n        try:\n            proxmox.nodes.get()  # Fetches all nodes to verify connection\n            self.pm_password = pm_password\n            Log.success('authentication successful')\n            return proxmox\n        except Exception as e:\n            Log.error(f'Authentication failed')\n        return None\n\n    def check(self):\n        checks = [\n            self.command.check_terraform(),\n            self.command.check_ansible()\n        ]\n        return all(checks)\n\n    @staticmethod\n    def _color_vm_state(state):\n        if state == \"running\":\n            return f'[green]{state}[/green]'\n        elif state == \"stopped\":\n            return f'[red]{state}[/red]'\n        return f'[yellow]{state}[/yellow]'\n\n    def status(self):\n        proxmox = self._get_proxmox()\n        if proxmox is not None:\n            pool_members = proxmox.pools(self.pm_pool).get()\n            running_vms_containers = []\n\n            table = Table()\n            table.add_column('VM Id')\n            table.add_column('Name')\n            table.add_column('hostname')\n            table.add_column('Status')\n            table.add_column('Type')\n            table.add_column('IP')\n\n            for member in pool_members['members']:\n                # Check for QEMU VMs (type 'qemu') and LXC containers (type 'lxc')\n                if member['type'] in ['qemu', 'lxc']:\n                    # Fetch the status of the VM/container to see if it's running\n                    node = member['node']\n                    vmid = member['vmid']\n                    ip_address = \"No IP Found\"\n\n                    if member['type'] == 'qemu':\n                        vm_status = proxmox.nodes(node).qemu(vmid).status.current.get()\n                        vm_config = proxmox.nodes(node).qemu(vmid).config.get()  # To get the name\n                    else:\n                        vm_status = proxmox.nodes(node).lxc(vmid).status.current.get()\n                        vm_config = proxmox.nodes(node).lxc(vmid).config.get()  # To get the name\n\n                    vm_name = vm_config.get('name', f\"VMID-{vmid}\")\n\n                    vm_hostname = \"\"\n                    # Proceed if the VM or container is running\n                    if vm_status['status'] == 'running':\n                        ip_address = \"unreachable\"\n\n                        # Get IP for QEMU VMs by querying the network interface\n                        if member['type'] == 'qemu':\n                            try:\n                                hostname = proxmox.nodes(node).qemu(vmid).agent('get-host-name').get()\n                                vm_hostname = hostname['result'].get('host-name')\n                                net_info = proxmox.nodes(node).qemu(vmid).agent('network-get-interfaces').get()\n                                for interface in net_info['result']:\n                                    for ip in interface.get('ip-addresses', []):\n                                        # Only interested in non-loopback IPs (ignoring 127.x.x.x)\n                                        if not ip['ip-address'].startswith('127') and not ip['ip-address'].startswith('::1') and not ip['ip-address'].startswith('fe80'):\n                                            if ip_address == 'unreachable':\n                                                ip_address = ip['ip-address']\n                                            else:\n                                                ip_address += ', ' + ip['ip-address']\n                            except Exception as e:\n                                Log.error(f\"Error fetching IP for QEMU VM {vmid}: {e}\")\n\n                        # Get IP for LXC containers by querying the network status\n                        elif member['type'] == 'lxc':\n                            vm_hostname = vm_name\n                            try:\n                                for key, value in vm_config.items():\n                                    if key.startswith('net'):\n                                        ip_address = value.get('ip', ip_address)\n                            except Exception as e:\n                                Log.error(f\"Error fetching IP for LXC {vmid}: {e}\")\n\n                    table.add_row(str(vmid), vm_name, vm_hostname, self._color_vm_state(vm_status['status']), member['type'], ip_address)\n            print(table)\n\n    def start(self):\n        proxmox = self._get_proxmox()\n        if proxmox is not None:\n            try:\n                pool_members = proxmox.pools(self.pm_pool).get()\n                for member in pool_members['members']:\n                    node = member['node']\n                    vmid = member['vmid']\n                    vm_type = member['type']\n                    # Start QEMU VM\n                    if vm_type == 'qemu':\n                        try:\n                            Log.info(f\"Starting QEMU VM {vmid} on node {node}...\")\n                            proxmox.nodes(node).qemu(vmid).status.start.post()\n                            Log.success(f\"QEMU VM {vmid} started successfully.\")\n                        except Exception as e:\n                            Log.error(f\"Error starting QEMU VM {vmid}: {e}\")\n                    # Start LXC container\n                    elif vm_type == 'lxc':\n                        try:\n                            Log.info(f\"Starting LXC container {vmid} on node {node}...\")\n                            proxmox.nodes(node).lxc(vmid).status.start.post()\n                            Log.success(f\"LXC container {vmid} started successfully.\")\n                        except Exception as e:\n                            Log.error(f\"Error starting LXC container {vmid}: {e}\")\n            except Exception as e:\n                print(f\"Error fetching pool details or starting VMs/containers: {e}\")\n\n    def stop(self):\n        proxmox = self._get_proxmox()\n        if proxmox is not None:\n            try:\n                pool_members = proxmox.pools(self.pm_pool).get()\n                for member in pool_members['members']:\n                    node = member['node']\n                    vmid = member['vmid']\n                    vm_type = member['type']\n                    # Start QEMU VM\n                    if vm_type == 'qemu':\n                        try:\n                            Log.info(f\"Stopping QEMU VM {vmid} on node {node}...\")\n                            proxmox.nodes(node).qemu(vmid).status.stop.post()\n                            Log.success(f\"QEMU VM {vmid} stopped successfully.\")\n                        except Exception as e:\n                            Log.error(f\"Error starting QEMU VM {vmid}: {e}\")\n                    # Start LXC container\n                    elif vm_type == 'lxc':\n                        try:\n                            Log.info(f\"Stopping LXC container {vmid} on node {node}...\")\n                            proxmox.nodes(node).lxc(vmid).status.stop.post()\n                            Log.success(f\"LXC container {vmid} stopped successfully.\")\n                        except Exception as e:\n                            Log.error(f\"Error starting LXC container {vmid}: {e}\")\n            except Exception as e:\n                Log.error(f\"Error fetching pool details or starting VMs/containers: {e}\")\n\n    def start_vm(self, vmid):\n        proxmox = self._get_proxmox()\n        if proxmox is not None:\n            # Start the VM\n            try:\n                Log.info(f\"Starting VM with VMID {vmid} on node {self.pm_node}...\")\n                proxmox.nodes(self.pm_node).qemu(vmid).status.start.post()\n                Log.success(f\"VM {vmid} started successfully.\")\n            except Exception as e:\n                Log.error(f\"Error starting VM {vmid}: {e}\")\n\n    def stop_vm(self, vmid):\n        proxmox = self._get_proxmox()\n        if proxmox is not None:\n            # Start the VM\n            try:\n                Log.info(f\"Stopping VM with VMID {vmid} on node {self.pm_node}...\")\n                proxmox.nodes(self.pm_node).qemu(vmid).status.stop.post()\n                Log.success(f\"VM {vmid} stopped successfully.\")\n            except Exception as e:\n                Log.error(f\"Error stopping VM {vmid}: {e}\")\n\n    def destroy_vm(self, vm_name):\n        pass\n"
  },
  {
    "path": "goad/provider/terraform/terraform.py",
    "content": "from goad.provider.provider import Provider\nimport os\nimport shutil\nfrom goad.goadpath import GoadPath\nfrom goad.log import Log\n\n\nclass TerraformProvider(Provider):\n\n    def check(self):\n        checks = [\n            self.command.check_terraform(),\n            self.command.check_rsync()\n        ]\n        return all(checks)\n\n    def install(self):\n        self.command.run_terraform(['init'], self.path)\n        self.command.run_terraform(['plan'], self.path)\n        return self.command.run_terraform(['apply'], self.path)\n\n    def destroy(self):\n        return self.command.run_terraform(['destroy'], self.path)\n\n    def start(self):\n        pass\n\n    def stop(self):\n        pass\n\n    def status(self):\n        pass\n\n    def start_vm(self, vm_name):\n        pass\n\n    def stop_vm(self, vm_name):\n        pass\n\n    def destroy_vm(self, vm_name):\n        pass\n\n    def ssh_jumpbox(self):\n        pass\n"
  },
  {
    "path": "goad/provider/vagrant/vagrant.py",
    "content": "from goad.provider.provider import Provider\n\n\nclass VagrantProvider(Provider):\n\n    def __init__(self, lab_name):\n        super().__init__(lab_name)\n        self.jumpbox_setup_script = 'setup_local_jumpbox.sh'\n\n    def check(self):\n        checks = [\n            self.command.check_vagrant(),\n            self.command.check_disk(),\n            self.command.check_ram(),\n            self.command.check_ansible(),\n            self.command.check_vagrant_plugin('vagrant-reload')\n        ]\n        return all(checks)\n\n    def install(self):\n        return self.command.run_vagrant(['up'], self.path)\n\n    def destroy(self):\n        return self.command.run_vagrant(['destroy'], self.path)\n\n    def start(self):\n        return self.command.run_vagrant(['up'], self.path)\n\n    def stop(self):\n        return self.command.run_vagrant(['halt'], self.path)\n\n    def status(self):\n        return self.command.run_vagrant(['status'], self.path)\n\n    def snapshot(self):\n        return self.command.run_vagrant(['snapshot', 'push'], self.path)\n\n    def reset(self):\n        return self.command.run_vagrant(['snapshot', 'pop', '--no-delete'], self.path)\n\n    def destroy_vm(self, vm_name):\n        return self.command.run_vagrant(['destroy', vm_name], self.path)\n\n    def start_vm(self, vm_name):\n        return self.command.run_vagrant(['up', vm_name], self.path)\n\n    def stop_vm(self, vm_name):\n        return self.command.run_vagrant(['halt', vm_name], self.path)\n\n    def remove_extension(self, extension_name):\n        # TODO one day if possible\n        pass\n\n    def get_jumpbox_ip(self, ip_range=''):\n        return ip_range + '.3'\n"
  },
  {
    "path": "goad/provider/vagrant/virtualbox.py",
    "content": "from goad.provider.vagrant.vagrant import VagrantProvider\nfrom goad.utils import *\n\n\nclass VirtualboxProvider(VagrantProvider):\n    provider_name = VIRTUALBOX\n    default_provisioner = PROVISIONING_LOCAL\n    allowed_provisioners = [PROVISIONING_LOCAL, PROVISIONING_RUNNER, PROVISIONING_DOCKER, PROVISIONING_VM]\n\n    def check(self):\n        checks = [\n            super().check(),\n            self.command.check_virtualbox(),\n            self.command.check_vagrant_plugin('vagrant-vbguest', False)\n        ]\n        return all(checks)\n"
  },
  {
    "path": "goad/provider/vagrant/vmware.py",
    "content": "from goad.provider.vagrant.vagrant import VagrantProvider\nfrom goad.utils import *\n\n\nclass VmwareProvider(VagrantProvider):\n    provider_name = VMWARE\n    default_provisioner = PROVISIONING_LOCAL\n    allowed_provisioners = [PROVISIONING_LOCAL, PROVISIONING_RUNNER, PROVISIONING_DOCKER, PROVISIONING_VM]\n\n    def check(self):\n        checks = [\n            super().check(),\n            self.command.check_vmware(),\n            self.command.check_vmware_utility(),\n            self.command.check_vagrant_plugin('vagrant-vmware-desktop', True)\n        ]\n        return all(checks)\n"
  },
  {
    "path": "goad/provider/vagrant/vmware_esxi.py",
    "content": "from goad.provider.vagrant.vagrant import VagrantProvider\nfrom goad.utils import *\n\n\nclass VmwareEsxiProvider(VagrantProvider):\n    provider_name = VMWARE_ESXI\n    default_provisioner = PROVISIONING_LOCAL\n    allowed_provisioners = [PROVISIONING_LOCAL, PROVISIONING_RUNNER, PROVISIONING_DOCKER, PROVISIONING_VM]\n\n    def check(self):\n        checks = [\n            super().check(),\n            self.command.check_vagrant_plugin('vagrant-vmware-esxi', True),\n            self.command.check_vagrant_plugin('vagrant-env', True),\n            self.command.check_ovftool()\n        ]\n        return all(checks)\n"
  },
  {
    "path": "goad/provisioner/ansible/ansible.py",
    "content": "import os.path\nimport yaml\nfrom goad.utils import *\nfrom goad.log import Log\nfrom goad.provisioner.provisioner import Provisioner\nfrom goad.goadpath import GoadPath\n\n\nclass Ansible(Provisioner):\n\n    def _get_lab_inventory(self, lab_name, provider_name):\n        inventory = []\n        # Lab inventory\n        lab_inventory = GoadPath.get_lab_inventory_file(lab_name)\n        if os.path.isfile(lab_inventory):\n            inventory.append(lab_inventory)\n            Log.success(f'Lab inventory : {lab_inventory} file found')\n        # lab instance inventory\n        instance_inventory = self.instance_path + os.path.sep + 'inventory'\n        if os.path.isfile(instance_inventory):\n            inventory.append(instance_inventory)\n            Log.success(f'Provider inventory : {instance_inventory} file found')\n        return inventory\n\n    def _get_global_inventory(self):\n        # Global inventory\n        global_inventory = GoadPath.get_global_inventory_path()\n        if os.path.isfile(global_inventory):\n            Log.success(f'Global inventory : {global_inventory} file found')\n            return global_inventory\n        return None\n\n    def get_inventory(self, lab_name, provider_name):\n        Log.info('Loading inventory')\n        inventory = self._get_lab_inventory(lab_name, provider_name)\n        global_inventory = self._get_global_inventory()\n        if global_inventory is not None:\n            inventory.append(global_inventory)\n        return inventory\n\n    def get_playbook_list(self, lab_name):\n        Log.info('Loading playbook list')\n        playbook_organisation_file = GoadPath.get_playbooks_lab_config()\n        playbook_list = []\n        with open(playbook_organisation_file, 'r') as playbooks:\n            data_loaded = yaml.safe_load(playbooks)\n        if lab_name in data_loaded:\n            playbook_datas = data_loaded[lab_name]\n        else:\n            playbook_datas = data_loaded['default']\n\n        # validate playbooks\n        for playbook in playbook_datas:\n            playbook_path = GoadPath.get_provisioner_path() + playbook\n            if not os.path.isfile(playbook_path):\n                Log.error(f'{playbook} not valid, file {playbook_path} not found')\n            else:\n                playbook_list.append(playbook)\n                Log.success(f'{playbook} file found')\n        return playbook_list\n\n    def run(self, playbook=None):\n        inventory = self.get_inventory(self.lab_name, self.provider_name)\n        provision_result = False\n        if playbook is None:\n            playbooks = self.get_playbook_list(self.lab_name)\n            for playbook in playbooks:\n                provision_result = self.run_playbook(playbook, inventory)\n                if not provision_result:\n                    Log.error(f'Something wrong during the provisioning task : {playbook}')\n                    return False\n        else:\n            provision_result = self.run_playbook(playbook, inventory)\n        return provision_result\n\n    def run_extension(self, extension, current_instance_extensions_name, install=True):\n        inventory = self._get_lab_inventory(self.lab_name, self.provider_name)\n\n        # add the inventory of other enabled extensions\n        for instances_extension_name in current_instance_extensions_name:\n            if instances_extension_name != extension.name:\n                other_extension_inventory = self.instance_path + os.path.sep + instances_extension_name + '_inventory'\n                if other_extension_inventory is not None:\n                    inventory.append(other_extension_inventory)\n\n        # add the current extension inventory at the end\n        extension_inventory = self.instance_path + os.path.sep + extension.name + '_inventory'\n        if extension_inventory is not None:\n            inventory.append(extension_inventory)\n\n        global_inventory = self._get_global_inventory()\n        if global_inventory is not None:\n            inventory.append(global_inventory)\n\n        playbook = extension.get_playbook(install)\n        extension_ansible_path = extension.get_ansible_path()\n\n        provision_result = self.run_playbook(playbook, inventory, playbook_path=extension_ansible_path)\n        if not provision_result:\n            Log.error(f'Something wrong during the provisioning task : {playbook}')\n            return False\n        return provision_result\n\n    def run_from(self, task):\n        inventory = self.get_inventory(self.lab_name, self.provider_name)\n        playbooks = self.get_playbook_list(self.lab_name)\n\n        if task == '' or task is None:\n            Log.error('Missing playbook to start from')\n            Log.info('Playbook list :')\n            for playbook in playbooks:\n                Log.info(f' - {playbook}')\n            return False\n\n        skip = True\n        for playbook in playbooks:\n            if playbook == task:\n                skip = False\n            if skip:\n                Log.info(f'skip {playbook}')\n            else:\n                provision_result = self.run_playbook(playbook, inventory)\n                if not provision_result:\n                    Log.error(f'Something wrong during the provisioning task : {playbook}')\n                    return False\n        return True\n\n    def run_playbook(self, playbook, inventories, tries=3, timeout=30, playbook_path=None):\n        # abstract\n        pass\n\n    def get_disable_vagrant_inventory(self):\n        Log.info('Loading inventory')\n        inventory = []\n        lab_inventory = self.instance_path + os.path.sep + 'inventory_disable_vagrant'\n        if os.path.isfile(lab_inventory):\n            inventory.append(lab_inventory)\n            Log.success(f'Lab inventory disable_vagrant : {lab_inventory} file found')\n        global_inventory = self._get_global_inventory()\n        if global_inventory is not None:\n            inventory.append(global_inventory)\n        return inventory\n\n    def run_disable_vagrant(self, disable_vagrant=True):\n        inventory = self.get_disable_vagrant_inventory()\n        if disable_vagrant:\n            playbook = 'disable_vagrant.yml'\n        else:\n            playbook = 'enable_vagrant.yml'\n        provision_result = self.run_playbook(playbook, inventory)\n        if not provision_result:\n            Log.error(f'Something wrong during the provisioning task : {playbook}')\n            return False\n        return provision_result\n"
  },
  {
    "path": "goad/provisioner/ansible/docker.py",
    "content": "from goad.log import Log\nfrom goad.utils import *\nfrom goad.goadpath import GoadPath\nfrom goad.provisioner.ansible.ansible import Ansible\nimport subprocess\nimport os\n\n\nclass DockerAnsibleProvisionerCmd(Ansible):\n    provisioner_name = 'docker'\n\n    def __init__(self, lab_name, provider):\n        super().__init__(lab_name, provider)\n        self.remote_project_path = '/goad'\n        if self.is_current_user_in_docker_group():\n            self.sudo = ''\n        else:\n            self.sudo = 'sudo'\n        self.check_docker_image()\n\n    def is_current_user_in_docker_group(self):\n        try:\n            # Get the current logged-in user\n            user = os.getlogin()\n            # Run the 'groups' command to get the groups the user belongs to\n            output = subprocess.check_output(['groups', user], text=True)\n            # Check if 'sudo' is in the output\n            if 'docker' in output.split():\n                Log.info('Current user is in docker group')\n                return True\n            else:\n                Log.info('Current user is not in docker group, we will use \"sudo\" before docker commands')\n                return False\n        except subprocess.CalledProcessError:\n            # If the command fails, return False\n            return False\n\n    def check_docker_image(self):\n        if not self.command.run_command(f'{self.sudo} docker images |grep -c \"goadansible\"', GoadPath.get_project_path()):\n            Log.error('Docker image goadansible not found')\n            Log.info('You should build the docker image with : \"sudo docker build -t goadansible .\"')\n        else:\n            Log.success('Docker image exist')\n\n    def run_playbook(self, playbook, inventories, tries=3, timeout=30, playbook_path=None):\n        remote_inventories = []\n        for inventory in inventories:\n            remote_inventories.append(Utils.transform_local_path_to_remote_path(inventory, self.remote_project_path))\n        command = f'-i {\" -i \".join(remote_inventories)} {playbook}'\n        Log.info(f'Run playbook : {playbook} with inventory file(s) : {\", \".join(remote_inventories)}')\n        run_complete = False\n        nb_try = 0\n        if playbook_path is not None:\n            ansible_path = Utils.transform_local_path_to_remote_path(playbook_path, self.remote_project_path)\n        else:\n            ansible_path = '/goad/ansible'\n        while not run_complete:\n            nb_try += 1\n            run_complete = self.command.run_docker_ansible(command, GoadPath.get_project_path(), ansible_path, self.sudo)\n            if not run_complete and nb_try > tries:\n                Log.error('3 fails abort.')\n                break\n        return run_complete\n"
  },
  {
    "path": "goad/provisioner/ansible/local.py",
    "content": "from goad.log import Log\nfrom goad.utils import *\nfrom goad.provisioner.ansible.ansible import Ansible\n\n\nclass LocalAnsibleProvisionerCmd(Ansible):\n    provisioner_name = PROVISIONING_LOCAL\n\n    def run_playbook(self, playbook, inventories, tries=3, timeout=30, playbook_path=None):\n        if playbook_path is None:\n            playbook_path = self.path\n\n        Log.info(f'Run playbook : {playbook} with inventory file(s) : {\", \".join(inventories)}')\n\n        args = f'-i {\" -i \".join(inventories)} {playbook}'\n\n        run_complete = False\n        nb_try = 0\n        while not run_complete:\n            nb_try += 1\n            run_complete = self.command.run_ansible(args, playbook_path)\n            if not run_complete and nb_try > tries:\n                Log.error('3 fails abort.')\n                break\n        return run_complete\n"
  },
  {
    "path": "goad/provisioner/ansible/remote.py",
    "content": "from goad.log import Log\nfrom goad.provisioner.ansible.ansible import Ansible\nfrom goad.utils import *\n\n\nclass RemoteAnsibleProvisioner(Ansible):\n    provisioner_name = PROVISIONING_REMOTE\n    use_jumpbox = True\n\n    def __init__(self, lab_name, provider):\n        super().__init__(lab_name, provider)\n        self.jumpbox = None\n        self.remote_project_path = '/home/goad/GOAD'\n\n    def prepare_jumpbox(self, jumpbox_ip):\n        if self.jumpbox is not None:\n            self.jumpbox.ip = jumpbox_ip\n            self.jumpbox.sync_sources()\n            self.jumpbox.provision()\n        else:\n            Log.error('no jumpbox for provisioner')\n\n    def sync_source_jumpbox(self):\n        if self.jumpbox is not None:\n            self.jumpbox.sync_sources()\n        else:\n            Log.error('no jumpbox for provisioner')\n\n    def run(self, playbook=None):\n        if self.jumpbox is None:\n            Log.error('Jumpbox not set')\n            return False\n        return super().run(playbook)\n\n    def run_playbook(self, playbook, inventories, tries=3, timeout=30, playbook_path=None):\n        if playbook_path is None:\n            playbook_path = self.remote_project_path + '/ansible/'\n        else:\n            playbook_path = Utils.transform_local_path_to_remote_path(playbook_path, self.remote_project_path)\n\n        remote_inventories = []\n        for inventory in inventories:\n            remote_inventories.append(Utils.transform_local_path_to_remote_path(inventory, self.remote_project_path))\n        command = f'/home/goad/.local/bin/ansible-playbook -i {\" -i \".join(remote_inventories)} {playbook}'\n\n        Log.info(f'Run playbook : {playbook} with inventory file(s) : {\", \".join(remote_inventories)}')\n        Log.cmd('command')\n\n        run_complete = False\n        nb_try = 0\n        while not run_complete:\n            nb_try += 1\n            run_complete = self.jumpbox.run_command(command, playbook_path)\n\n            if not run_complete and nb_try > tries:\n                Log.error('3 fails abort.')\n                break\n        return run_complete\n"
  },
  {
    "path": "goad/provisioner/ansible/runner.py",
    "content": "import time\n\nimport ansible_runner\nfrom goad.utils import *\nfrom goad.log import Log\nfrom goad.provisioner.ansible.ansible import Ansible\n\n\nclass LocalAnsibleProvisionerEmbed(Ansible):\n    provisioner_name = PROVISIONING_RUNNER\n\n    def run_playbook(self, playbook, inventories, tries=3, timeout=30, playbook_path=None):\n        if playbook_path is None:\n            playbook_path = self.path\n        Log.info(f'Run playbook : {playbook} with inventory file(s) : {\", \".join(inventories)}')\n        Log.cmd(f'ansible-playbook -i {\" -i \".join(inventories)} {playbook}')\n\n        run_complete = False\n        runner_result = None\n        nb_try = 0\n        while not run_complete:\n            nb_try += 1\n            runner_result = ansible_runner.run(private_data_dir=self.path + 'private_data_dir',\n                                               playbook=playbook_path + playbook,\n                                               inventory=inventories)\n            if len(runner_result.stats['ok'].keys()) >= 1:\n                run_complete = True\n            if len(runner_result.stats['dark'].keys()) >= 1:\n                Log.error('Unreachable vm wait 30 sec and restart ansible')\n                time.sleep(30)\n                run_complete = False\n            if len(runner_result.stats['failures'].keys()) >= 1:\n                Log.error(f'Error during playbook iteration {str(nb_try)}, restart')\n                run_complete = False\n            if nb_try > tries:\n                Log.error('3 fails abort.')\n                break\n        # print(runner_result.stats)\n        return run_complete\n\n"
  },
  {
    "path": "goad/provisioner/ansible/vm.py",
    "content": "from goad.log import Log\nfrom goad.provisioner.ansible.ansible import Ansible\nfrom goad.utils import *\n\n\nclass VmAnsibleProvisioner(Ansible):\n    provisioner_name = PROVISIONING_VM\n    use_jumpbox = True\n\n    def __init__(self, lab_name, provider):\n        super().__init__(lab_name, provider)\n        self.jumpbox = None\n        self.remote_project_path = '/home/vagrant/GOAD'\n\n    def prepare_jumpbox(self, jumpbox_ip):\n        if self.jumpbox is not None:\n            self.jumpbox.ip = jumpbox_ip\n            self.jumpbox.ssh_key = self.jumpbox.get_jumpbox_key()\n            if self.jumpbox.ssh_key is not None:\n                self.jumpbox.provision()\n                self.jumpbox.sync_sources()\n            else:\n                Log.error(\"The ssh key for the provider can't be found, error.\")\n        else:\n            Log.error('no jumpbox for provisioner')\n\n    def sync_source_jumpbox(self):\n        if self.jumpbox is not None:\n            self.jumpbox.sync_sources()\n        else:\n            Log.error('no jumpbox for provisioner')\n\n    def run(self, playbook=None):\n        if self.jumpbox is None:\n            Log.error('Jumpbox not set')\n            return False\n        return super().run(playbook)\n\n    def run_playbook(self, playbook, inventories, tries=3, timeout=30, playbook_path=None):\n        if playbook_path is None:\n            playbook_path = self.remote_project_path + '/ansible/'\n        else:\n            playbook_path = Utils.transform_local_path_to_remote_path(playbook_path, self.remote_project_path)\n\n        remote_inventories = []\n        for inventory in inventories:\n            remote_inventories.append(Utils.transform_local_path_to_remote_path(inventory, self.remote_project_path))\n        command = f'/home/vagrant/.local/bin/ansible-playbook -i {\" -i \".join(remote_inventories)} {playbook}'\n\n        Log.info(f'Run playbook : {playbook} with inventory file(s) : {\", \".join(remote_inventories)}')\n        Log.cmd('command')\n\n        run_complete = False\n        nb_try = 0\n        while not run_complete:\n            nb_try += 1\n            run_complete = self.jumpbox.run_command(command, playbook_path)\n\n            if not run_complete and nb_try > tries:\n                Log.error('3 fails abort.')\n                break\n        return run_complete\n"
  },
  {
    "path": "goad/provisioner/provisioner.py",
    "content": "from abc import ABC\nfrom goad.command.linux import LinuxCommand\nfrom goad.command.wsl import WslCommand\nfrom goad.goadpath import GoadPath\nfrom goad.utils import Utils\nfrom goad.command.cmd_factory import CommandFactory\n\n\nclass Provisioner(ABC):\n    lab_name = ''\n    provider_name = ''\n    provisioner_name = None\n    use_jumpbox = False\n\n    def __init__(self, lab_name, provider):\n        self.lab_name = lab_name\n        self.provider_name = provider.provider_name\n        self.provider = provider\n        self.path = GoadPath.get_provisioner_path()\n        self.instance_path = ''\n        self.command = CommandFactory.get_command()\n\n    def set_instance_path(self, path):\n        self.instance_path = path\n\n    def run(self, arg):\n        pass\n\n    def run_extension(self, arg, current_instance_extensions):\n        pass\n\n    def run_from(self, arg):\n        pass\n\n    def update_jumpbox_ip(self, ip):\n        pass\n"
  },
  {
    "path": "goad/provisioner/provisioner_factory.py",
    "content": "from goad.utils import *\nfrom goad.dependencies import Dependencies\nfrom goad.jumpbox import JumpBox\nfrom goad.local_jumpbox import LocalJumpBox\n\nif Dependencies.provisioner_local_enabled:\n    from goad.provisioner.ansible.local import LocalAnsibleProvisionerCmd\nif Dependencies.provisioner_runner_enabled:\n    from goad.provisioner.ansible.runner import LocalAnsibleProvisionerEmbed\nif Dependencies.provisioner_remote_enabled:\n    from goad.provisioner.ansible.remote import RemoteAnsibleProvisioner\nif Dependencies.provisioner_docker_enabled:\n    from goad.provisioner.ansible.docker import DockerAnsibleProvisionerCmd\nif Dependencies.provisioner_vm_enabled:\n    from goad.provisioner.ansible.vm import VmAnsibleProvisioner\n\n\nclass ProvisionerFactory:\n\n    @staticmethod\n    def get_provisioner(provisioner_name, instance, is_instance_creation):\n        lab_name = instance.lab_name\n        provider = instance.provider\n        provisioner = None\n        if provisioner_name == PROVISIONING_LOCAL and Dependencies.provisioner_local_enabled:\n            provisioner = LocalAnsibleProvisionerCmd(lab_name, provider)\n        elif provisioner_name == PROVISIONING_REMOTE and Dependencies.provisioner_remote_enabled:\n            provisioner = RemoteAnsibleProvisioner(lab_name, provider)\n            provisioner.jumpbox = JumpBox(instance, is_instance_creation)\n        elif provisioner_name == PROVISIONING_RUNNER and Dependencies.provisioner_runner_enabled:\n            provisioner = LocalAnsibleProvisionerEmbed(lab_name, provider)\n        elif provisioner_name == PROVISIONING_DOCKER and Dependencies.provisioner_docker_enabled:\n            provisioner = DockerAnsibleProvisionerCmd(lab_name, provider)\n        elif provisioner_name == PROVISIONING_VM and Dependencies.provisioner_vm_enabled:\n            provisioner = VmAnsibleProvisioner(lab_name, provider)\n            provisioner.jumpbox = LocalJumpBox(instance, is_instance_creation)\n        return provisioner\n"
  },
  {
    "path": "goad/settings.py",
    "content": "from goad.log import Log\nfrom goad.utils import *\nfrom goad.dependencies import Dependencies\n\n\nclass Settings:\n    \"\"\"\n    This class keep the current settings\n    \"\"\"\n\n    def __init__(self, lab_manager):\n        self.lab_manager = lab_manager\n        self.lab_name = None\n        self.provider_name = None\n        self.provisioner_name = None\n        self.extensions_name = []\n        self.ip_range = None\n\n    def update(self, instance):\n        \"\"\"\n        Update current settings with an instance values\n        :param instance: LabInstance object\n        \"\"\"\n        self.lab_name = instance.lab_name\n        self.provider_name = instance.provider_name\n        self.provisioner_name = instance.provisioner_name\n        self.ip_range = instance.ip_range\n        self.extensions_name = instance.extensions\n\n    def show(self):\n        Log.info(f'Current Lab         : {self.lab_name}')\n        Log.info(f'Current Provider    : {self.provider_name}')\n        Log.info(f'Current Provisioner : {self.provisioner_name}')\n        if self.provider_name != LUDUS:\n            Log.info(f'Current IP range    : {self.ip_range}.X')\n        Log.info(f'Extension(s)        :')\n        for extension in self.extensions_name:\n            Log.info(f' - {extension}')\n\n    def inline(self):\n        if self.provider_name == LUDUS:\n            return f'{self.lab_name}/{self.provider_name}/{self.provisioner_name}'\n        else:\n            return f'{self.lab_name}/{self.provider_name}/{self.provisioner_name}/{self.ip_range}.X'\n\n    def set_lab_name(self, lab_name, refresh=True):\n        \"\"\"\n        Set current lab settings if the lab is changed, the provider is changed too\n        :param refresh: if setting the lab refresh the provider\n        :param lab_name:\n        :return: lab_name\n        \"\"\"\n        if self.lab_manager.is_lab_exist(lab_name):\n            # set lab\n            self.lab_name = lab_name\n            if refresh:\n                self._refresh_provider()\n        else:\n            Log.error(f'Lab {lab_name} not found')\n            Log.info('fallback to GOAD lab')\n            self.set_lab_name('GOAD')\n        return self.lab_name\n\n    def _refresh_provider(self):\n        \"\"\"\n        refresh the provider according to current status\n        this function will change the provider with the first found if the selected provider does not exist\n        \"\"\"\n        # compare previous provider\n        old_provider_name = self.provider_name\n        lab = self.lab_manager.get_lab(self.lab_name)\n        if lab is not None:\n            if lab.get_provider(old_provider_name) is None:\n                Log.info(f'Provider {old_provider_name} not found in lab {self.lab_name}')\n                new_provider_name = lab.get_first_provider_name()\n                Log.info(f'Change provider to {new_provider_name}')\n                self.set_provider_name(new_provider_name)\n\n    def set_provider_name(self, provider_name, refresh=True):\n        if self.lab_name is not None:\n            lab = self.lab_manager.get_lab(self.lab_name)\n            provider = lab.get_provider(provider_name)\n            if provider is not None:\n                self.provider_name = provider.provider_name\n                if refresh:\n                    self.refresh_provisioner(provider)\n            else:\n                Log.error(f'provider {provider_name} not found')\n                new_provider_name = lab.get_first_provider_name()\n                Log.info(f'fallback to first provider found: {new_provider_name}, change it with : \"set_provider\"')\n                self.set_provider_name(new_provider_name)\n        else:\n            raise ValueError(f\"can't set provider because lab_name is not set\")\n        return self.provider_name\n\n    def refresh_provisioner(self, provider):\n        \"\"\"\n        refresh the provisioner according to current status\n        this function will change the provisioner if the selected provider does not exist or is not adapted\n        \"\"\"\n        if self.provisioner_name is None:\n            default_provisioner = provider.default_provisioner\n            self.set_provisioner_name(default_provisioner)\n        else:\n            self.set_provisioner_name(self.provisioner_name)\n\n    def set_provisioner_name(self, provisioner_name):\n        if self.lab_name is None:\n            raise ValueError(f'current_lab not set')\n\n        if self.provider_name is None:\n            raise ValueError(f'current provider is not set')\n\n        lab = self.lab_manager.get_lab(self.lab_name)\n        provider = lab.get_provider(self.provider_name)\n\n        if provisioner_name not in provider.allowed_provisioners:\n            Log.warning(f'provisioner method {provisioner_name} is not allowed for provider {self.provider_name}')\n            Log.info(f'automatic changing provisioner method {provisioner_name} to default for this provider : {provider.default_provisioner}')\n            self.provisioner_name = provider.default_provisioner\n        else:\n            if ((provisioner_name == PROVISIONING_RUNNER and not Dependencies.provisioner_runner_enabled) or\n                    (provisioner_name == PROVISIONING_DOCKER and not Dependencies.provisioner_docker_enabled) or (\n                    provisioner_name == PROVISIONING_LOCAL and not Dependencies.provisioner_local_enabled) or (\n                    provisioner_name == PROVISIONING_REMOTE and not Dependencies.provisioner_remote_enabled)):\n                Log.warning(f'provisioner method {provisioner_name} is not enabled')\n                Log.info(f'automatic changing provisioner method {provisioner_name} to default for this provider : {provider.default_provisioner}')\n                self.provisioner_name = provider.default_provisioner\n            else:\n                self.provisioner_name = provisioner_name\n        return self.provisioner_name\n\n    def set_ip_range(self, ip_range):\n        error = False\n        try:\n            parts = ip_range.split('.')\n            if len(parts) >= 3 and all(0 <= int(parts[i]) < 256 for i in range(0, 3)):\n                self.ip_range = f'{parts[0]}.{parts[1]}.{parts[2]}'\n                return self.ip_range\n            else:\n                error = True\n        except ValueError:\n            error = True  # one of the 'parts' not convertible to integer\n        except (AttributeError, TypeError):\n            error = True  # `ip` isn't even a string\n        if error:\n            Log.error(f'entered value not valid')\n            Log.info(f'fallback to default ip range: 192.168.56.x')\n            self.ip_range = '192.168.56'\n        return self.ip_range\n\n    def set_extensions(self, extensions_name):\n        self.extensions_name = []\n        if self.lab_name is not None:\n            lab = self.lab_manager.get_lab(self.lab_name)\n            for extension_name in extensions_name:\n                if lab.get_extension(extension_name) is not None:\n                    self.extensions_name.append(extension_name)\n                else:\n                    Log.error(f'Extension {extension_name} is not available for this lab.')\n        else:\n            raise ValueError(f\"can't set extension because lab_name is not set\")\n        return self.extensions_name\n"
  },
  {
    "path": "goad/utils.py",
    "content": "from pathlib import Path\nimport os\nimport random\nimport string\nimport ipaddress\nimport platform\n\n# constants\nLAB = 'lab'\nPROVIDER = 'provider'\nPROVISIONER = 'provisioner'\nIP_RANGE = 'ip_range'\n\n# log level\nINFO = 5\nVERBOSE = 2\nDEBUG = 1\n\n# providers\nAWS = 'aws'\nVIRTUALBOX = 'virtualbox'\nAZURE = 'azure'\nVMWARE = 'vmware'\nVMWARE_ESXI = 'vmware_esxi'\nPROXMOX = 'proxmox'\nLUDUS = 'ludus'\nALLOWED_PROVIDERS = [AWS, VIRTUALBOX, AZURE, VMWARE, VMWARE_ESXI, PROXMOX, LUDUS]\n\n# provisioning method\nPROVISIONING_LOCAL = 'local'\nPROVISIONING_RUNNER = 'runner'\nPROVISIONING_REMOTE = 'remote'\nPROVISIONING_VM = 'vm'\nPROVISIONING_DOCKER = 'docker'\nALLOWED_PROVISIONER = [PROVISIONING_LOCAL, PROVISIONING_REMOTE, PROVISIONING_VM, PROVISIONING_RUNNER, PROVISIONING_DOCKER]\n\n# provisioner allowed\n# AWS_ALLOWED_PROVISIONER = [PROVISIONING_REMOTE]\n# AZURE_ALLOWED_PROVISIONER = [PROVISIONING_REMOTE]\n# PROXMOX_ALLOWED_PROVISIONER = [PROVISIONING_LOCAL, PROVISIONING_RUNNER]\n# VMWARE_ALLOWED_PROVISIONER = [PROVISIONING_LOCAL, PROVISIONING_RUNNER, PROVISIONING_DOCKER]\n# VIRTUALBOX_ALLOWED_PROVISIONER = [PROVISIONING_LOCAL, PROVISIONING_RUNNER, PROVISIONING_DOCKER]\n# LUDUS_ALLOWED_PROVISIONER = [PROVISIONING_LOCAL, PROVISIONING_RUNNER]\n\nproject_path = os.path.normpath(os.path.dirname(os.path.abspath(__file__)) + os.path.sep + '..')\n\n# instance status\nCREATED = 'not provided'\nPROVIDED = 'ready for provisioning'\nREADY = 'installed'\n\n# tasks\nTASK_INSTALL = 'install'\nTASK_CHECK = 'check'\nTASK_START = 'start'\nTASK_STOP = 'stop'\nTASK_RESTART = 'restart'\nTASK_DESTROY = 'destroy'\nTASK_STATUS = 'status'\nTASK_SNAPSHOT = 'snapshot'\nTASK_RESET = 'reset'\n\n\nclass SingletonMeta(type):\n    _instances = {}\n\n    def __call__(cls, *args, **kwargs):\n        if cls not in cls._instances:\n            cls._instances[cls] = super().__call__(*args, **kwargs)\n        return cls._instances[cls]\n\n\nclass Utils:\n\n    @staticmethod\n    def is_wsl():\n        version = platform.uname().release\n        if version.endswith(\"-Microsoft\"):\n            return True\n        elif version.endswith(\"microsoft-standard-WSL2\"):\n            return True\n        return False\n\n    @staticmethod\n    def is_windows():\n        if not Utils.is_wsl() and platform.system() == 'Windows':\n            return True\n        return False\n\n    @staticmethod\n    def confirm(message):\n        result = input(f\"{message}\")\n        if result == \"y\" or result == \"Y\" or result == \"Yes\":\n            return True\n        return False\n\n    @staticmethod\n    def is_valid_ipv4(ip):\n        try:\n            # Try to create an IPv4 object from the input\n            ipaddress.IPv4Address(ip)\n            return True\n        except ValueError:\n            return False\n\n    @staticmethod\n    def list_folders(path):\n        if os.path.isdir(path):\n            return [p.name for p in Path(path).iterdir() if p.is_dir()]\n        else:\n            return []\n\n    @staticmethod\n    def list_files(path):\n        f = []\n        for (dirpath, dirnames, filenames) in os.walk(path):\n            f.extend(filenames)\n            break\n        return f\n\n    @staticmethod\n    def get_relative_path(path):\n        return path[len(project_path):]\n\n    @staticmethod\n    def transform_local_path_to_remote_path(origin, remote_project_path):\n        result_path = remote_project_path + origin[len(project_path):]\n        if Utils.is_windows():\n            result_path = result_path.replace('\\\\', '/')\n        return result_path\n\n    @staticmethod\n    def get_random_string(length):\n        # choose from all lowercase letter\n        letters = string.ascii_lowercase\n        result_str = ''.join(random.choice(letters) for i in range(length))\n        return result_str\n\n    @staticmethod\n    def replace_in_file(filename, search_string, new_string):\n        if os.path.isfile(filename):\n            # Read in the file\n            with open(filename, 'r') as file:\n                filedata = file.read()\n\n            # Replace the target string\n            filedata = filedata.replace(search_string, new_string)\n\n            # Write the file out again\n            with open(filename, 'w') as file:\n                file.write(filedata)\n            return True\n        return False\n"
  },
  {
    "path": "goad.py",
    "content": "import cmd\nimport argparse\nimport sys\nimport time\nfrom goad.config import Config\nfrom goad.log import Log\nfrom goad.exceptions import JumpBoxInitFailed\nfrom goad.menu import print_menu, print_logo\nfrom goad.infos import *\n\n\nclass Goad(cmd.Cmd):\n\n    def __init__(self, args):\n        super().__init__()\n        # get the arguments\n        self.args = args\n        # prepare config, read configuration file and merge with args\n        config = Config()\n        config.merge_config(args)\n        # prepare lab controller to manage labs\n        # import lab manager after the loading of the dependencies to allow disabling some provider and provisioning method\n        from goad.lab_manager import LabManager\n        self.lab_manager = LabManager().init(config, args)\n\n        if args.task == '' or args.task is None:\n            Log.info('Start Loading default instance')\n            # load instance marked as default only if no args are provided\n            self.lab_manager.load_default_instance()\n\n        self.welcome()\n        # set current lab and provider\n        self.refresh_prompt()\n\n    def welcome(self):\n        Log.info('lab instances :')\n        # show instances tables\n        self.lab_manager.lab_instances.show_instances(current_instance_id=self.lab_manager.get_current_instance_id())\n        # show current configuration\n        # self.lab_manager.show_settings()\n\n    def refresh_prompt(self):\n        if self.lab_manager.get_current_instance_id() == '':\n            self.prompt = f\"\\n{self.lab_manager.inline_settings()} > \"\n        else:\n            self.prompt = f\"\\n{self.lab_manager.inline_settings()} ({self.lab_manager.get_current_instance_id()}) > \"\n\n    def default(self, line):\n        print()\n\n    def do_help(self, arg):\n        print_menu(self.lab_manager)\n\n    def do_exit(self, arg):\n        print('bye')\n        return True\n\n    # main commands\n    def do_check(self, arg=''):\n        self.lab_manager.check()\n\n    def do_status(self, arg=''):\n        if self.lab_manager.get_current_instance():\n            self.lab_manager.get_current_instance().provider.status()\n\n    def do_install(self, arg=''):\n        self.do_create()\n\n    def do_start(self, arg=''):\n        if self.lab_manager.get_current_instance_provider():\n            self.lab_manager.get_current_instance_provider().start()\n\n    def do_start_vm(self, arg):\n        if arg == '':\n            Log.error('missing virtual machine name')\n            Log.info('start_vm <vm>')\n        else:\n            self.lab_manager.get_current_instance_provider().start_vm(arg)\n\n    def do_stop(self, arg=''):\n        if self.lab_manager.get_current_instance_provider():\n            self.lab_manager.get_current_instance_provider().stop()\n\n    def do_stop_vm(self, arg):\n        if arg == '':\n            Log.error('missing virtual machine name')\n            Log.info('stop_vm <vm>')\n        else:\n            self.lab_manager.get_current_instance_provider().stop_vm(arg)\n\n    def do_destroy(self, arg=''):\n        if self.lab_manager.get_current_instance_provider():\n            self.lab_manager.get_current_instance_provider().destroy()\n\n    def do_destroy_vm(self, arg):\n        if arg == '':\n            Log.error('missing virtual machine name')\n            Log.info('destroy_vm <vm>')\n        else:\n            self.lab_manager.get_current_instance_provider().destroy_vm(arg)\n\n    def do_snapshot(self, arg=''):\n        self.do_stop()\n        if self.lab_manager.get_current_instance_provider():\n            self.lab_manager.get_current_instance_provider().snapshot()\n        self.do_start()\n    \n    def do_reset(self, arg=''):\n        self.do_stop()\n        if self.lab_manager.get_current_instance_provider():\n            self.lab_manager.get_current_instance_provider().reset()\n        self.do_start()\n\n    def do_provide(self, arg=''):\n        result = self.lab_manager.get_current_instance_provider().install()\n        if result:\n            self.lab_manager.get_current_instance().set_status(PROVIDED)\n            # if ip range change after provisioning\n            if self.lab_manager.get_current_instance_provider().update_ip_range:\n                Log.info('Update IP range')\n                new_range = self.lab_manager.get_current_instance_provider().get_ip_range()\n                if new_range is not None:\n                    Log.info(f'new range : {new_range}')\n                    self.lab_manager.get_current_instance().update_ip_range(new_range)\n                    Log.info(f'reload instance')\n                    # reload instance\n                    instance_id = self.lab_manager.get_current_instance_id()\n                    self.do_load(instance_id)\n                    self.refresh_prompt()\n\n    def do_provision(self, arg):\n        if arg == '':\n            Log.error('missing playbook argument')\n            Log.info('provision <playbook>')\n        else:\n            start = time.time()\n            # run playbook\n            self.lab_manager.get_current_instance_provisioner().run(arg)\n            time_provision = time.ctime(time.time() - start)[11:19]\n            Log.info(f'Provisioned with {arg} in {time_provision}')\n\n    def do_provision_lab(self, arg=''):\n        start = time.time()\n        provision_result = self.lab_manager.get_current_instance_provisioner().run()\n        if provision_result:\n            self.lab_manager.get_current_instance().set_status(READY)\n            time_provision = time.ctime(time.time() - start)[11:19]\n            Log.info(f'Lab successfully provisioned in {time_provision}')\n        return provision_result\n\n    def do_provision_lab_from(self, arg):\n        start = time.time()\n        provision_result = self.lab_manager.get_current_instance_provisioner().run_from(arg)\n        if provision_result:\n            self.lab_manager.get_current_instance().set_status(READY)\n            time_provision = time.ctime(time.time() - start)[11:19]\n            Log.info(f'Provisioned from {arg} in {time_provision}')\n\n    def do_sync_source_jumpbox(self, arg=''):\n        if self.lab_manager.get_current_instance_provisioner().use_jumpbox:\n            self.lab_manager.get_current_instance_provisioner().sync_source_jumpbox()\n\n    def do_prepare_jumpbox(self, arg=''):\n        if self.lab_manager.get_current_instance_provisioner().use_jumpbox:\n            jumpbox_ip = self.lab_manager.get_current_instance_provider().get_jumpbox_ip(self.lab_manager.get_ip_range())\n            if jumpbox_ip is not None:\n                self.lab_manager.get_current_instance_provisioner().prepare_jumpbox(jumpbox_ip)\n            else:\n                Log.error('cannot find jumpbox ip')\n\n    def do_config(self, arg):\n        self.lab_manager.show_settings()\n\n    def do_ssh_jumpbox(self, arg):\n        if self.lab_manager.get_current_instance_provisioner().use_jumpbox:\n            try:\n                jump_box = self.lab_manager.get_current_instance_provisioner().jumpbox\n                jump_box.ssh()\n            except JumpBoxInitFailed as e:\n                Log.error('Jumpbox retrieve connection info failed, abort')\n        else:\n            Log.error('No jump box for this provider')\n\n    def do_ssh_jumpbox_proxy(self, arg):\n        if self.lab_manager.get_current_instance_provisioner().use_jumpbox:\n            try:\n                jump_box = self.lab_manager.get_current_instance_provisioner().jumpbox\n                if arg.isnumeric() and 1024 < int(arg) <= 65535:\n                    jump_box.ssh_proxy(arg)\n                else:\n                    Log.error(f'Port value invalid : {arg}')\n            except JumpBoxInitFailed as e:\n                Log.error('Jumpbox retrieve connection info failed, abort')\n        else:\n            Log.error('No jump box for this provider')\n\n    # configuration\n    def do_set_lab(self, arg):\n        \"\"\"\n        Change/Set the lab to use\n        :param arg: lab name\n        :return: void\n        \"\"\"\n        if arg == '':\n            Log.error('missing lab argument')\n            Log.info('set_lab <lab>')\n        else:\n            try:\n                self.lab_manager.set_lab(arg)\n                self.refresh_prompt()\n            except ValueError as err:\n                Log.error(err.args[0])\n                Log.info('Available labs :')\n                for lab in self.lab_manager.labs:\n                    Log.info(f' - {lab}')\n\n    def complete_set_lab(self, text, line, begidx, endidx):\n        options = self.lab_manager.get_labs_options()\n        if not text:\n            completions = options\n        else:\n            completions = [option for option in options if option.startswith(text)]\n        return completions\n\n    def do_set_provider(self, arg):\n        \"\"\"\n        Change/Set the provider to use\n        :param arg: provider name\n        :return: void\n        \"\"\"\n        if arg == '':\n            Log.error('missing provider argument')\n            Log.info(f'set_provider <provider> (allowed values : {\",\".join(ALLOWED_PROVIDERS)})')\n        else:\n            try:\n                self.lab_manager.set_provider(arg)\n                self.refresh_prompt()\n            except ValueError as err:\n                Log.error(err.args[0])\n\n    def complete_set_provider(self, text, line, begidx, endidx):\n        options = self.lab_manager.get_provider_options()\n        if not text:\n            completions = options\n        else:\n            completions = [option for option in options if option.startswith(text)]\n        return completions\n\n    def do_set_provisioning_method(self, arg):\n        if arg == '':\n            Log.error('missing provisioner argument')\n            Log.info(f'set_provisioner <provisioner> (allowed values : {\",\".join(ALLOWED_PROVISIONER)})')\n        else:\n            try:\n                self.lab_manager.set_provisioner(arg)\n                self.refresh_prompt()\n            except ValueError as err:\n                Log.error(err.args[0])\n\n    def complete_set_provisioning_method(self, text, line, begidx, endidx):\n        options = self.lab_manager.provisioning_method_options()\n        if not text:\n            completions = options\n        else:\n            completions = [option for option in options if option.startswith(text)]\n        return completions\n\n    def do_set_ip_range(self, arg):\n        if arg == '':\n            Log.error('missing ip_start argument')\n            Log.info(f'set_ip_start <ip_start>')\n        else:\n            self.lab_manager.set_ip_range(arg)\n            self.refresh_prompt()\n\n    def do_set_extensions(self, arg):\n        if arg == '':\n            Log.error('missing extensions arguments')\n            Log.info(f'set_extensions <extension1> <extension2> ...')\n        else:\n            extensions_name = arg.split(' ')\n            self.lab_manager.set_extensions(extensions_name)\n            self.refresh_prompt()\n\n    def do_list_extensions(self, arg):\n        if self.lab_manager.get_current_instance_lab() is not None:\n            self.lab_manager.get_current_instance_lab().show_extensions()\n        else:\n            self.lab_manager.get_lab(self.lab_manager.get_current_lab_name()).show_extensions()\n\n    def do_install_extension(self, arg):\n        if arg == '':\n            Log.error('missing extension argument')\n            Log.info(f'provision_extension <extension>')\n        else:\n            Log.info('start install extension')\n            if self.lab_manager.current_instance is not None:\n                extension_name = arg\n                extension = self.lab_manager.get_current_instance_lab().get_extension(extension_name)\n                if extension is not None:\n                    # enable and create files\n                    self.lab_manager.get_current_instance().enable_extension(extension_name)\n                    # # start lab with extensions files (vagrant up / terraform plan)\n                    self.lab_manager.get_current_instance_provider().install()\n                    # # provision extension\n                    self.do_provision_extension(extension_name)\n                else:\n                    Log.error(f'extension {extension_name} not found abort')\n            else:\n                Log.error('Install extension can only be run from an instance')\n\n    def do_provision_extension(self, arg):\n        if arg == '':\n            Log.error('missing extension argument')\n            Log.info(f'provision_extension <extension>')\n        else:\n            extension_name = arg\n            start = time.time()\n            current_instance_extensions_name = self.lab_manager.get_current_instance().extensions\n            if extension_name in current_instance_extensions_name:\n                self.do_sync_source_jumpbox()\n                extension = self.lab_manager.get_current_instance_lab().get_extension(extension_name)\n                provision_result = self.lab_manager.get_current_instance_provisioner().run_extension(extension, current_instance_extensions_name)\n                if provision_result:\n                    time_provision = time.ctime(time.time() - start)[11:19]\n                    Log.info(f'Provision extension done in {time_provision}')\n            else:\n                Log.error(f'extension {extension_name} not enabled in instance abort')\n\n    def do_labs(self, arg):\n        show_labs_providers_table(self.lab_manager.get_labs())\n\n    def do_show_list_providers(self, arg):\n        show_labs_providers_list(self.lab_manager.get_labs())\n\n    def do_update_instance_files(self, arg):\n        self.lab_manager.update_instance_files()\n\n    def do_create(self, arg=''):\n        if self.lab_manager.get_current_instance() is not None:\n            self.do_install_instance()\n        else:\n            Log.success('Current Settings')\n            self.lab_manager.current_settings.show()\n            print()\n            if Utils.confirm('Create lab with theses settings ? (y/N)'):\n                Log.info('Create instance folder')\n                self.lab_manager.create_instance()\n                Log.info('Launch providing')\n                self.do_provide()\n                if self.lab_manager.get_current_instance().get_status() == PROVIDED:\n                    Log.info('Prepare jumpbox if needed')\n                    self.do_prepare_jumpbox()\n                    Log.info('Launch provisioning')\n                    provision_result = self.do_provision_lab()\n                    if provision_result:\n                        for extension_name in self.lab_manager.current_settings.extensions_name:\n                            Log.info(f'Start installation of extension : {extension_name}')\n                            self.do_install_extension(extension_name)\n                    self.refresh_prompt()\n                else:\n                    Log.error('Providing error stop')\n\n    def do_install_instance(self, arg=''):\n        Log.info('Launch providing')\n        self.do_provide()\n        if self.lab_manager.get_current_instance().get_status() == PROVIDED:\n            Log.info('Prepare jumpbox if needed')\n            self.do_prepare_jumpbox()\n            Log.info('Launch provisioning')\n            provision_result = self.do_provision_lab()\n            if provision_result:\n                for extension_name in self.lab_manager.current_settings.extensions_name:\n                    Log.info(f'Start installation of extension : {extension_name}')\n                    self.do_install_extension(extension_name)\n            self.refresh_prompt()\n        else:\n            Log.error('Providing error stop')\n\n    def do_create_empty(self, arg=''):\n        Log.info('Create instance folder')\n        self.lab_manager.create_instance()\n\n    def do_set_as_default(self, arg):\n        self.lab_manager.set_as_default_instance()\n\n    # load alias\n    def do_use(self, arg):\n        self.do_load(arg)\n\n    def complete_use(self, text, line, begidx, endidx):\n        return self.complete_load(text, line, begidx, endidx)\n\n    # load alias\n    def do_cd(self, arg):\n        if arg == '..':\n            self.do_unload()\n        else:\n            self.do_load(arg)\n\n    def complete_cd(self, text, line, begidx, endidx):\n        return self.complete_load(text, line, begidx, endidx)\n\n    def do_load(self, arg):\n        if arg == '':\n            Log.error('missing instance id argument')\n            Log.info(f'use_instance <instance_id>')\n        else:\n            self.lab_manager.load_instance(arg)\n            if self.lab_manager.current_instance is not None:\n                self.lab_manager.lab_instances.show_instances(current_instance_id=self.lab_manager.get_current_instance_id(), filter_instance_id=self.lab_manager.get_current_instance_id())\n            self.refresh_prompt()\n\n    def complete_load(self, text, line, begidx, endidx):\n        options = self.lab_manager.get_instance_options()\n        if not text:\n            completions = options\n        else:\n            completions = [option for option in options if option.startswith(text)]\n        return completions\n\n    def do_unload(self, arg=''):\n        if self.lab_manager.get_current_instance_id() is not None:\n            self.lab_manager.unload_instance()\n            self.refresh_prompt()\n\n    def do_delete(self, arg):\n        if self.lab_manager.get_current_instance_id() is not None:\n            deleted = self.lab_manager.delete_instance()\n            if deleted:\n                self.refresh_prompt()\n\n    def do_disable_vagrant(self, arg):\n        start = time.time()\n        provision_result = self.lab_manager.get_current_instance_provisioner().run_disable_vagrant(disable_vagrant=True)\n        if provision_result:\n            time_provision = time.ctime(time.time() - start)[11:19]\n            Log.info(f'Disable vagrant done in {time_provision}')\n            Log.info(f'Please restart the lab to avoid administrator NT hash in lsass')\n\n    def do_enable_vagrant(self, arg):\n        start = time.time()\n        provision_result = self.lab_manager.get_current_instance_provisioner().run_disable_vagrant(disable_vagrant=False)\n        if provision_result:\n            time_provision = time.ctime(time.time() - start)[11:19]\n            Log.info(f'Enable vagrant done in {time_provision}')\n\n    # alias to list\n    def do_ls(self, arg=''):\n        self.do_list(arg)\n\n    def do_list(self, arg=''):\n        self.lab_manager.lab_instances.show_instances(current_instance_id=self.lab_manager.get_current_instance_id())\n\n\ndef parse_args():\n    task_help = 'tasks available : (install/start/stop/restart/destroy/status/show)'\n    parser = argparse.ArgumentParser(prog='goad.py',\n                                     description='Description : goad lab management console.',\n                                     epilog=show_help(), formatter_class=argparse.RawDescriptionHelpFormatter)\n    parser.add_argument(\"-t\", \"--task\", help=f\"{task_help}\", required=False)\n    parser.add_argument(\"-l\", \"--lab\", help=\"lab to use (default: GOAD)\", default='GOAD', required=False)\n    parser.add_argument(\"-p\", \"--provider\", help=\"provider to use (default: vmware)\", default='vmware', required=False)\n    parser.add_argument(\"-ip\", \"--ip_range\", help=\"ip range to use (default: 192.168.56)\", default='', required=False)\n    parser.add_argument(\"-m\", \"--method\", help=\"deploy method to use (default: local)\", default='local', required=False)\n    parser.add_argument(\"-i\", \"--instance\", help=\"use a specific instance (use default if not selected)\", required=False)\n    parser.add_argument(\"-e\", \"--extensions\", help=\"extensions to use\", action='append', required=False)\n    parser.add_argument(\"-a\", \"--ansible_only\", help=\"run only provisioning (ansible) on instance (-i) (for task install only)\", required=False)\n    parser.add_argument(\"-r\", \"--run_playbook\", help=\"run only one ansible playbook on instance (-i) (for task install only)\", required=False)\n    parser.add_argument(\"-d\", \"--disable_dependencies\", help=\"disable_dependencies\", action='append', required=False)\n    args = parser.parse_args()\n    return args\n\n\ndef show_help():\n    return '''\nExample :\n - Install GOAD on virtualbox : python3 goad.py -t install -l GOAD -p virtualbox\n - Launch GOAD interactive console : python3 goad.py\n'''\n\n\nif __name__ == '__main__':\n    print_logo()\n    args = parse_args()\n    goad = Goad(args)\n\n    if args is None or args.task is None:\n        goad.cmdloop()\n    else:\n        if args.instance is not None:\n            goad.do_load(args.instance)\n\n        if args.run_playbook is not None or args.ansible_only is not None:\n            if args.instance is None:\n                Log.error('Instance must be selected (-i) to use --run_playbook (-r) or --ansible_only (-a)')\n                sys.exit(1)\n\n        # Command line args like the old goad.sh commands\n        if args.task is not None:\n            if args.task == 'install':\n                if args.instance is not None:\n                    if args.run_playbook is not None:\n                        goad.do_provision(args.run_playbook)\n                    elif args.ansible_only:\n                        goad.do_provision_lab()\n                    else:\n                        goad.do_install_instance()\n                else:\n                    goad.do_install()\n            elif args.task == 'check':\n                goad.do_check()\n            elif args.task == 'start':\n                goad.do_start()\n            elif args.task == 'stop':\n                goad.do_stop()\n            elif args.task == 'restart':\n                goad.do_stop()\n                goad.do_start()\n            elif args.task == 'destroy':\n                goad.do_destroy()\n            elif args.task == 'status':\n                goad.do_status()\n            elif args.task == 'snapshot':\n                goad.do_snapshot()\n            elif args.task == 'reset':\n                goad.do_reset()\n            elif args.task == 'show':\n                pass\n"
  },
  {
    "path": "goad.sh",
    "content": "#!/usr/bin/env bash\n\npy=python3\nvenv=\"$HOME/.goad/.venv\"\nrequirement_file=\"requirements.yml\"\n\nif [ ! -d \"$venv\" ]\nthen\n  # Get the Python version (removes 'Python' from output)\n  version=$($py --version 2>&1 | awk '{print $2}')\n  echo \"Python version in use : $version\"\n  # Convert the version to comparable format (removes the dot and treats it as an integer)\n  version_numeric=$(echo $version | awk -F. '{printf \"%d%02d%02d\\n\", $1, $2, $3}')\n  # Check if the version is >= 3.8.0\n  if [ \"$version_numeric\" -ge 30800 ]; then\n      # echo \"Python version is >= 3.8.0\n      echo 'python version >= 3.8 ok'\n      if [ \"$version_numeric\" -lt 31100 ]; then\n        # python version < 3.11\n        requirement_file=\"requirements.yml\"\n      else\n        # python version >= 3.11\n        requirement_file=\"requirements_311.yml\"\n      fi\n  else\n      echo \"Python version is < 3.8 please update python before install\"\n      exit\n  fi\n\n  if [ \"$($py -m venv -h 2>/dev/null | grep -i 'usage:')\" ]; then\n    echo \"venv module is installed. continue\"\n  else\n    echo \"venv module is not installed.\"\n    echo \"please install $py-venv according to your system\"\n    echo \"exit\"\n    exit 0\n  fi\n\n  echo '[+] venv not found, start python venv creation'\n  mkdir -p ~/.goad\n  $py -m venv $venv\n  source $venv/bin/activate\n  if [ $? -eq 0 ]; then\n    $py -m pip install --upgrade pip\n    export SETUPTOOLS_USE_DISTUTILS=stdlib\n    $py -m pip install -r $requirement_file\n    cd ansible\n    ansible-galaxy install -r $requirement_file\n    cd -\n  else\n    echo \"Error in venv creation\"\n    rm -rf $venv\n    exit 0\n  fi\nfi\n\n# launch the app\nsource $venv/bin/activate\n$py goad.py $@\ndeactivate\n"
  },
  {
    "path": "goad_docker.sh",
    "content": "#!/usr/bin/env bash\n\npy=python3\nvenv=\"$HOME/.goad/.venvdocker\"\n\nif [ ! -d \"$venv\" ]\nthen\n  # Get the Python version (removes 'Python' from output)\n  version=$($py --version 2>&1 | awk '{print $2}')\n  # Convert the version to comparable format (removes the dot and treats it as an integer)\n  version_numeric=$(echo $version | awk -F. '{printf \"%d%02d%02d\\n\", $1, $2, $3}')\n  # Check if the version is >= 3.8.0 and < 3.12.0\n  if [ \"$version_numeric\" -ge 30800 ]; then\n      # echo \"Python version is >= 3.8.0\"\n      echo 'python version ok'\n  else\n      echo \"Python version is outside the range >= 3.8.0\"\n      exit\n  fi\n\n  if $py -m venv --help > /dev/null 2>&1; then\n      echo \"venv module is installed. continue\"\n  else\n      echo \"venv module is not installed.\"\n      echo \"please install python-venv according to your system\"\n      echo \"exit\"\n      exit 0\n  fi\n  echo '[+] venv not found, start python venv creation'\n  mkdir -p ~/.goad\n  $py -m venv $venv\n  source $venv/bin/activate\n  $py -m pip install --upgrade pip\n  export SETUPTOOLS_USE_DISTUTILS=stdlib\n  $py -m pip install -r noansible_requirements.yml\nfi\n\nif groups $USER | grep &>/dev/null '\\bdocker\\b'; then\n  echo \"User is in the docker group\"\n  use_sudo=\"\"\nelse\n  echo \"User is not in the docker group\"\n  use_sudo=\"sudo\"\nfi\n\nALREADY_BUILD=$($use_sudo docker images |grep -c \"goadansible\")\nif [[ $ALREADY_BUILD -eq 0 ]]; then\n  echo \"[+] Build container\"\n  $use_sudo docker build -t goadansible .\n  echo \"${OK} Container goadansible creation complete\"\nfi\n\necho \"goad with docker, disable local and runner provisioner\"\n# launch the app\nsource $venv/bin/activate\n$py goad.py -m docker -d local -d runner $@\ndeactivate\n"
  },
  {
    "path": "guacamole.yml",
    "content": "---\n# GUACAMOLE MYSQL\nmysql_root_password: \"ohmygoadchangeme\"\nmysql_root_password_update: true\nguacamole_db: guacamole\nguacamole_db_username: guacamole\nguacamole_db_password: ohmygoadchangeme\n# GUACAMOLE\nlayout: \"fr-fr-azerty\"\nguacadmin_password: \"ohmygoadchangeme\"\nguacamole_users:\n  - name: \"user\"\n    pass: \"ohmygoadchangeme\"\n"
  },
  {
    "path": "noansible_requirements.yml",
    "content": "rich\npsutil\nJinja2\npyyaml\n# AZURE\nazure-identity\nazure-mgmt-compute\nazure-mgmt-network\n# AWS\nboto3\n# Proxmox\nproxmoxer\nrequests"
  },
  {
    "path": "packer/proxmox/.gitignore",
    "content": "config.auto.pkrvars.hcl\nscripts/sysprep/CloudbaseInitSetup_Stable_x64.msi\n"
  },
  {
    "path": "packer/proxmox/README.md",
    "content": "# Promox VM packer\n\n## Infos \n[https://mayfly277.github.io/posts/GOAD-on-proxmox-part2-packer/](https://mayfly277.github.io/posts/GOAD-on-proxmox-part2-packer/)\n\n## Windows iso\n\nWindows iso evaluation to download and put inside the iso storage of proxmox\n\n- [Windows-10-22h2_x64_en-us.iso](https://software-static.download.prss.microsoft.com/dbazure/988969d5-f34g-4e03-ac9d-1f9786c66750/19045.2006.220908-0225.22h2_release_svc_refresh_CLIENTENTERPRISEEVAL_OEMRET_x64FRE_en-us.iso)\n- [windows_server_2016_14393.0_eval_x64.iso](https://software-download.microsoft.com/download/pr/Windows_Server_2016_Datacenter_EVAL_en-us_14393_refresh.ISO)\n- [windows_server2019_x64FREE_en-us.iso](https://software-static.download.prss.microsoft.com/dbazure/988969d5-f34g-4e03-ac9d-1f9786c66749/17763.3650.221105-1748.rs5_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso)\n\n- Be sure to name the iso like the name inside \n## Cloudbase init \n\n- Download here : https://cloudbase.it/cloudbase-init/\n- Put the msi at : /packer/proxmox/scripts/sysprep/CloudbaseInitSetup_Stable_x64.msi (54,7M)\n\n\n## Windows update\n- If you want to create updated template change the `<!-- no updates -->` and `<!-- WITH WINDOWS UPDATES ` comment in the answerfiles/Autounattend.xml files.\n\n\n## Prepare\n\n```bash\nsudo apt-get install mkisofs\ncd /root/GOAD/packer/proxmox/\n./build_proxmox_iso.sh\n```\n- Put the packer/proxmox/iso/scripts_withcloudinit.iso into proxmox's iso folder\n\n## Configure\n\n```bash\ncp config.auto.pkrvars.hcl.template config.auto.pkrvars.hcl\n```\n- And adapt the value to your proxmox config\n\n## ubuntu vm : install packer\n\n```bash\napt update\napt -y install apt-transport-https ca-certificates curl software-properties-common\ncurl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -\napt-add-repository \"deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main\"\napt update\napt install packer\n```\n\n## BUILD\n\n```\npacker validate -var-file=config.json windows_server2019_proxmox.json\npacker build -var-file=config.json windows_server2019_proxmox.json\n```"
  },
  {
    "path": "packer/proxmox/answer_files/10_proxmox_cloudinit/Autounattend.xml",
    "content": "    <?xml version=\"1.0\" encoding=\"utf-8\"?>\n    <unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\n        <servicing/>\n        <settings pass=\"windowsPE\">\n            <component name=\"Microsoft-Windows-PnpCustomizationsWinPE\"\n                publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\"\n                versionScope=\"nonSxS\" processorArchitecture=\"amd64\"\n                xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\">\n\n                <!--\n                    This makes the VirtIO drivers available to Windows, assuming that\n                    the VirtIO driver disk at https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso\n                    (see https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html#virtio-win-direct-downloads)\n                    is available as drive F:\n                -->\n                <DriverPaths>\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"2\">\n                        <Path>F:\\viostor\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"3\">\n                        <Path>F:\\NetKVM\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"4\">\n                        <Path>F:\\Balloon\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"5\">\n                        <Path>F:\\pvpanic\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"6\">\n                        <Path>F:\\qemupciserial\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"7\">\n                        <Path>F:\\qxldod\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"8\">\n                        <Path>F:\\vioinput\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"9\">\n                        <Path>F:\\viorng\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"10\">\n                        <Path>F:\\vioscsi\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"11\">\n                        <Path>F:\\vioserial\\w10\\amd64</Path>\n                    </PathAndCredentials>\n                </DriverPaths>\n            </component>\n            \n            <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <DiskConfiguration>\n                    <Disk wcm:action=\"add\">\n                        <CreatePartitions>\n                            <CreatePartition wcm:action=\"add\">\n                                <Order>1</Order>\n                                <Type>Primary</Type>\n                                <Extend>true</Extend>\n                            </CreatePartition>\n                        </CreatePartitions>\n                        <ModifyPartitions>\n                            <ModifyPartition wcm:action=\"add\">\n                                <Extend>false</Extend>\n                                <Format>NTFS</Format>\n                                <Letter>C</Letter>\n                                <Order>1</Order>\n                                <PartitionID>1</PartitionID>\n                                <Label>Windows 10</Label>\n                            </ModifyPartition>\n                        </ModifyPartitions>\n                        <DiskID>0</DiskID>\n                        <WillWipeDisk>true</WillWipeDisk>\n                    </Disk>\n                    <WillShowUI>OnError</WillShowUI>\n                </DiskConfiguration>\n                <UserData>\n                    <AcceptEula>true</AcceptEula>\n                    <FullName>Vagrant</FullName>\n                    <Organization>Vagrant</Organization>\n\n                    <!--\n                        NOTF: If you are re-configuring this for use of a retail key\n                        and using a retail ISO, you need to adjust the <ProductKey> block\n                        below to look like this:\n\n                        <ProductKey>\n                            <Key>W269N-WFGWX-YVC9B-4J6C9-T83GX</Key>\n                            <WillShowUI>Never</WillShowUI>\n                        </ProductKey>\n\n                        Notice the addition of the `<Key>` element.\n                    -->\n\n                    <!-- Product Key from https://www.microsoft.com/en-us/evalcenter/evaluate-windows-10-enterprise -->\n                    <ProductKey>\n                        <WillShowUI>Never</WillShowUI>\n                    </ProductKey>\n                </UserData>\n                <ImageInstall>\n                    <OSImage>\n                        <InstallTo>\n                            <DiskID>0</DiskID>\n                            <PartitionID>1</PartitionID>\n                        </InstallTo>\n                        <WillShowUI>OnError</WillShowUI>\n                        <InstallToAvailablePartition>false</InstallToAvailablePartition>\n                        <InstallFrom>\n                            <MetaData wcm:action=\"add\">\n                                <Key>/IMAGE/NAME</Key>\n                                <Value>Windows 10 Enterprise Evaluation</Value>\n                            </MetaData>\n                        </InstallFrom>\n                    </OSImage>\n                </ImageInstall>\n            </component>\n            <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-International-Core-WinPE\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <SetupUILanguage>\n                    <UILanguage>en-US</UILanguage>\n                </SetupUILanguage>\n                <InputLocale>en-US</InputLocale>\n                <SystemLocale>en-US</SystemLocale>\n                <UILanguage>en-US</UILanguage>\n                <UILanguageFallback>en-US</UILanguageFallback>\n                <UserLocale>en-US</UserLocale>\n            </component>\n        </settings>\n        <settings pass=\"offlineServicing\">\n            <component name=\"Microsoft-Windows-LUA-Settings\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <EnableLUA>false</EnableLUA>\n            </component>\n        </settings>\n        <settings pass=\"oobeSystem\">\n            <component name=\"Microsoft-Windows-International-Core\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n                <InputLocale>en-US</InputLocale>\n                <SystemLocale>en-US</SystemLocale>\n                <UILanguage>en-US</UILanguage>\n                <UserLocale>en-US</UserLocale>\n            </component>\n            <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <UserAccounts>\n                    <AdministratorPassword>\n                        <Value>vagrant</Value>\n                        <PlainText>true</PlainText>\n                    </AdministratorPassword>\n                    <LocalAccounts>\n                        <LocalAccount wcm:action=\"add\">\n                            <Password>\n                                <Value>vagrant</Value>\n                                <PlainText>true</PlainText>\n                            </Password>\n                            <Description>Vagrant User</Description>\n                            <DisplayName>vagrant</DisplayName>\n                            <Group>administrators</Group>\n                            <Name>vagrant</Name>\n                        </LocalAccount>\n                    </LocalAccounts>\n                </UserAccounts>\n                <OOBE>\n                    <HideEULAPage>true</HideEULAPage>\n                    <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\n                    <NetworkLocation>Home</NetworkLocation>\n                    <ProtectYourPC>1</ProtectYourPC>\n                </OOBE>\n                <AutoLogon>\n                    <Password>\n                        <Value>vagrant</Value>\n                        <PlainText>true</PlainText>\n                    </Password>\n                    <Username>vagrant</Username>\n                    <Enabled>true</Enabled>\n                </AutoLogon>\n                <FirstLogonCommands>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                        <Description>Set Execution Policy 64 Bit</Description>\n                        <Order>1</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>C:\\Windows\\SysWOW64\\cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                        <Description>Set Execution Policy 32 Bit</Description>\n                        <Order>2</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c reg add \"HKLM\\System\\CurrentControlSet\\Control\\Network\\NewNetworkWindowOff\"</CommandLine>\n                        <Description>Network prompt</Description>\n                        <Order>3</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\fixnetwork.ps1</CommandLine>\n                        <Description>Fix public network</Description>\n                        <Order>4</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\disable-winrm.ps1</CommandLine>\n                        <Description>Disable WinRM</Description>\n                        <Order>5</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>\n                        <Order>6</Order>\n                        <Description>Show file extensions in Explorer</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine>\n                        <Order>7</Order>\n                        <Description>Enable QuickEdit mode</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine>\n                        <Order>8</Order>\n                        <Description>Show Run command in Start Menu</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine>\n                        <Order>9</Order>\n                        <Description>Show Administrative Tools in Start Menu</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine>\n                        <Order>10</Order>\n                        <Description>Zero Hibernation File</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine>\n                        <Order>11</Order>\n                        <Description>Disable Hibernation Mode</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c wmic useraccount where \"name='vagrant'\" set PasswordExpires=FALSE</CommandLine>\n                        <Order>12</Order>\n                        <Description>Disable password expiration for vagrant user</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v DefaultPassword /t REG_SZ /d \"vagrant\" /f</CommandLine>\n                        <Order>13</Order>\n                        <Description>Enable AutoLogon</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v AutoAdminLogon /t REG_SZ /d 1 /f</CommandLine>\n                        <Order>14</Order>\n                        <Description>Enable AutoLogon</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <Order>15</Order>\n                        <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"netsh advfirewall firewall set rule group='Windows Remote Management' new enable=yes\"</CommandLine>\n                        <Description>Enable windows RDP</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <Order>16</Order>\n                        <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"F:\\guest-agent\\qemu-ga-x86_64.msi /quiet\"</CommandLine>\n                        <Description>Drivers install</Description>\n                    </SynchronousCommand>\n                    <!--<SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"msiexec /i G:\\CloudbaseInitSetup_1_1_2_x64.msi /qn /l*v c:\\log.txt\"</CommandLine>\n                        <Description>Prepare for cloudinit</Description>\n                        <Order>20</Order>\n                    </SynchronousCommand> -->\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"G:\\Install-WMF3Hotfix.ps1\"</CommandLine>\n                        <Description>Install-WMF3Hotfix.ps1</Description>\n                        <Order>97</Order>\n                    </SynchronousCommand>\n                    <!-- no updates -->\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"G:\\ConfigureRemotingForAnsible.ps1\"</CommandLine>\n                        <Description>ConfigureRemotingForAnsible</Description>\n                        <Order>98</Order>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\enable-winrm.ps1</CommandLine>\n                        <Description>Enable WinRM</Description>\n                        <Order>99</Order>\n                    </SynchronousCommand>\n                    <!-- WITH WINDOWS UPDATES \n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c G:\\microsoft-updates.bat</CommandLine>\n                        <Order>98</Order>\n                        <Description>Enable Microsoft Updates</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\disable-screensaver.ps1</CommandLine>\n                        <Description>Disable Screensaver</Description>\n                        <Order>99</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\win-updates.ps1</CommandLine>\n                        <Description>Install Windows Updates</Description>\n                        <Order>100</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                     END WITH WINDOWS UPDATES -->\n                </FirstLogonCommands>\n                <ShowWindowsLive>false</ShowWindowsLive>\n            </component>\n        </settings>\n        <settings pass=\"specialize\">\n            <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <OEMInformation>\n                    <HelpCustomized>false</HelpCustomized>\n                </OEMInformation>\n                <!-- Rename computer here. -->\n                <ComputerName>vagrant-10</ComputerName>\n                <TimeZone>Romance Standard Time</TimeZone>\n                <RegisteredOwner/>\n            </component>\n            <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Security-SPP-UX\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <SkipAutoActivation>true</SkipAutoActivation>\n            </component>\n        </settings>\n        <cpi:offlineImage xmlns:cpi=\"urn:schemas-microsoft-com:cpi\" cpi:source=\"catalog:d:/sources/install_windows 7 ENTERPRISE.clg\"/>\n    </unattend>"
  },
  {
    "path": "packer/proxmox/answer_files/10_proxmox_cloudinit_uptodate/Autounattend.xml",
    "content": "    <?xml version=\"1.0\" encoding=\"utf-8\"?>\n    <unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\n        <servicing/>\n        <settings pass=\"windowsPE\">\n            <component name=\"Microsoft-Windows-PnpCustomizationsWinPE\"\n                publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\"\n                versionScope=\"nonSxS\" processorArchitecture=\"amd64\"\n                xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\">\n\n                <!--\n                    This makes the VirtIO drivers available to Windows, assuming that\n                    the VirtIO driver disk at https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso\n                    (see https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html#virtio-win-direct-downloads)\n                    is available as drive F:\n                -->\n                <DriverPaths>\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"2\">\n                        <Path>F:\\viostor\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"3\">\n                        <Path>F:\\NetKVM\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"4\">\n                        <Path>F:\\Balloon\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"5\">\n                        <Path>F:\\pvpanic\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"6\">\n                        <Path>F:\\qemupciserial\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"7\">\n                        <Path>F:\\qxldod\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"8\">\n                        <Path>F:\\vioinput\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"9\">\n                        <Path>F:\\viorng\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"10\">\n                        <Path>F:\\vioscsi\\w10\\amd64</Path>\n                    </PathAndCredentials>\n\n                    <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"11\">\n                        <Path>F:\\vioserial\\w10\\amd64</Path>\n                    </PathAndCredentials>\n                </DriverPaths>\n            </component>\n            \n            <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <DiskConfiguration>\n                    <Disk wcm:action=\"add\">\n                        <CreatePartitions>\n                            <CreatePartition wcm:action=\"add\">\n                                <Order>1</Order>\n                                <Type>Primary</Type>\n                                <Extend>true</Extend>\n                            </CreatePartition>\n                        </CreatePartitions>\n                        <ModifyPartitions>\n                            <ModifyPartition wcm:action=\"add\">\n                                <Extend>false</Extend>\n                                <Format>NTFS</Format>\n                                <Letter>C</Letter>\n                                <Order>1</Order>\n                                <PartitionID>1</PartitionID>\n                                <Label>Windows 10</Label>\n                            </ModifyPartition>\n                        </ModifyPartitions>\n                        <DiskID>0</DiskID>\n                        <WillWipeDisk>true</WillWipeDisk>\n                    </Disk>\n                    <WillShowUI>OnError</WillShowUI>\n                </DiskConfiguration>\n                <UserData>\n                    <AcceptEula>true</AcceptEula>\n                    <FullName>Vagrant</FullName>\n                    <Organization>Vagrant</Organization>\n\n                    <!--\n                        NOTF: If you are re-configuring this for use of a retail key\n                        and using a retail ISO, you need to adjust the <ProductKey> block\n                        below to look like this:\n\n                        <ProductKey>\n                            <Key>W269N-WFGWX-YVC9B-4J6C9-T83GX</Key>\n                            <WillShowUI>Never</WillShowUI>\n                        </ProductKey>\n\n                        Notice the addition of the `<Key>` element.\n                    -->\n\n                    <!-- Product Key from https://www.microsoft.com/en-us/evalcenter/evaluate-windows-10-enterprise -->\n                    <ProductKey>\n                        <WillShowUI>Never</WillShowUI>\n                    </ProductKey>\n                </UserData>\n                <ImageInstall>\n                    <OSImage>\n                        <InstallTo>\n                            <DiskID>0</DiskID>\n                            <PartitionID>1</PartitionID>\n                        </InstallTo>\n                        <WillShowUI>OnError</WillShowUI>\n                        <InstallToAvailablePartition>false</InstallToAvailablePartition>\n                        <InstallFrom>\n                            <MetaData wcm:action=\"add\">\n                                <Key>/IMAGE/NAME</Key>\n                                <Value>Windows 10 Enterprise Evaluation</Value>\n                            </MetaData>\n                        </InstallFrom>\n                    </OSImage>\n                </ImageInstall>\n            </component>\n            <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-International-Core-WinPE\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <SetupUILanguage>\n                    <UILanguage>en-US</UILanguage>\n                </SetupUILanguage>\n                <InputLocale>en-US</InputLocale>\n                <SystemLocale>en-US</SystemLocale>\n                <UILanguage>en-US</UILanguage>\n                <UILanguageFallback>en-US</UILanguageFallback>\n                <UserLocale>en-US</UserLocale>\n            </component>\n        </settings>\n        <settings pass=\"offlineServicing\">\n            <component name=\"Microsoft-Windows-LUA-Settings\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <EnableLUA>false</EnableLUA>\n            </component>\n        </settings>\n        <settings pass=\"oobeSystem\">\n            <component name=\"Microsoft-Windows-International-Core\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n                <InputLocale>en-US</InputLocale>\n                <SystemLocale>en-US</SystemLocale>\n                <UILanguage>en-US</UILanguage>\n                <UserLocale>en-US</UserLocale>\n            </component>\n            <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <UserAccounts>\n                    <AdministratorPassword>\n                        <Value>vagrant</Value>\n                        <PlainText>true</PlainText>\n                    </AdministratorPassword>\n                    <LocalAccounts>\n                        <LocalAccount wcm:action=\"add\">\n                            <Password>\n                                <Value>vagrant</Value>\n                                <PlainText>true</PlainText>\n                            </Password>\n                            <Description>Vagrant User</Description>\n                            <DisplayName>vagrant</DisplayName>\n                            <Group>administrators</Group>\n                            <Name>vagrant</Name>\n                        </LocalAccount>\n                    </LocalAccounts>\n                </UserAccounts>\n                <OOBE>\n                    <HideEULAPage>true</HideEULAPage>\n                    <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\n                    <NetworkLocation>Home</NetworkLocation>\n                    <ProtectYourPC>1</ProtectYourPC>\n                </OOBE>\n                <AutoLogon>\n                    <Password>\n                        <Value>vagrant</Value>\n                        <PlainText>true</PlainText>\n                    </Password>\n                    <Username>vagrant</Username>\n                    <Enabled>true</Enabled>\n                </AutoLogon>\n                <FirstLogonCommands>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                        <Description>Set Execution Policy 64 Bit</Description>\n                        <Order>1</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>C:\\Windows\\SysWOW64\\cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                        <Description>Set Execution Policy 32 Bit</Description>\n                        <Order>2</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c reg add \"HKLM\\System\\CurrentControlSet\\Control\\Network\\NewNetworkWindowOff\"</CommandLine>\n                        <Description>Network prompt</Description>\n                        <Order>3</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\fixnetwork.ps1</CommandLine>\n                        <Description>Fix public network</Description>\n                        <Order>4</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\disable-winrm.ps1</CommandLine>\n                        <Description>Disable WinRM</Description>\n                        <Order>5</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>\n                        <Order>6</Order>\n                        <Description>Show file extensions in Explorer</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine>\n                        <Order>7</Order>\n                        <Description>Enable QuickEdit mode</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine>\n                        <Order>8</Order>\n                        <Description>Show Run command in Start Menu</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine>\n                        <Order>9</Order>\n                        <Description>Show Administrative Tools in Start Menu</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine>\n                        <Order>10</Order>\n                        <Description>Zero Hibernation File</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine>\n                        <Order>11</Order>\n                        <Description>Disable Hibernation Mode</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c wmic useraccount where \"name='vagrant'\" set PasswordExpires=FALSE</CommandLine>\n                        <Order>12</Order>\n                        <Description>Disable password expiration for vagrant user</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v DefaultPassword /t REG_SZ /d \"vagrant\" /f</CommandLine>\n                        <Order>13</Order>\n                        <Description>Enable AutoLogon</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v AutoAdminLogon /t REG_SZ /d 1 /f</CommandLine>\n                        <Order>14</Order>\n                        <Description>Enable AutoLogon</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <Order>15</Order>\n                        <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"netsh advfirewall firewall set rule group='Windows Remote Management' new enable=yes\"</CommandLine>\n                        <Description>Enable windows RDP</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <Order>16</Order>\n                        <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"F:\\guest-agent\\qemu-ga-x86_64.msi /quiet\"</CommandLine>\n                        <Description>Drivers install</Description>\n                    </SynchronousCommand>\n                    <!--<SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"msiexec /i G:\\CloudbaseInitSetup_1_1_2_x64.msi /qn /l*v c:\\log.txt\"</CommandLine>\n                        <Description>Prepare for cloudinit</Description>\n                        <Order>20</Order>\n                    </SynchronousCommand> -->\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"G:\\Install-WMF3Hotfix.ps1\"</CommandLine>\n                        <Description>Install-WMF3Hotfix.ps1</Description>\n                        <Order>97</Order>\n                    </SynchronousCommand>\n                    <!-- no updates \n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"G:\\ConfigureRemotingForAnsible.ps1\"</CommandLine>\n                        <Description>ConfigureRemotingForAnsible</Description>\n                        <Order>98</Order>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\enable-winrm.ps1</CommandLine>\n                        <Description>Enable WinRM</Description>\n                        <Order>99</Order>\n                    </SynchronousCommand>\n                    WITH WINDOWS UPDATES -->\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c G:\\microsoft-updates.bat</CommandLine>\n                        <Order>98</Order>\n                        <Description>Enable Microsoft Updates</Description>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\disable-screensaver.ps1</CommandLine>\n                        <Description>Disable Screensaver</Description>\n                        <Order>99</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <SynchronousCommand wcm:action=\"add\">\n                        <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\win-updates.ps1</CommandLine>\n                        <Description>Install Windows Updates</Description>\n                        <Order>100</Order>\n                        <RequiresUserInput>true</RequiresUserInput>\n                    </SynchronousCommand>\n                    <!-- END WITH WINDOWS UPDATES -->\n                </FirstLogonCommands>\n                <ShowWindowsLive>false</ShowWindowsLive>\n            </component>\n        </settings>\n        <settings pass=\"specialize\">\n            <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <OEMInformation>\n                    <HelpCustomized>false</HelpCustomized>\n                </OEMInformation>\n                <!-- Rename computer here. -->\n                <ComputerName>vagrant-10</ComputerName>\n                <TimeZone>Romance Standard Time</TimeZone>\n                <RegisteredOwner/>\n            </component>\n            <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Security-SPP-UX\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n                <SkipAutoActivation>true</SkipAutoActivation>\n            </component>\n        </settings>\n        <cpi:offlineImage xmlns:cpi=\"urn:schemas-microsoft-com:cpi\" cpi:source=\"catalog:d:/sources/install_windows 7 ENTERPRISE.clg\"/>\n    </unattend>"
  },
  {
    "path": "packer/proxmox/answer_files/2016_proxmox_cloudinit/Autounattend.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\n    <settings pass=\"windowsPE\">\n        <component name=\"Microsoft-Windows-PnpCustomizationsWinPE\"\n            publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\"\n            versionScope=\"nonSxS\" processorArchitecture=\"amd64\"\n            xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\">\n\n            <!--\n                 This makes the VirtIO drivers available to Windows, assuming that\n                 the VirtIO driver disk at https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso\n                 (see https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html#virtio-win-direct-downloads)\n                 is available as drive F:\n            -->\n            <DriverPaths>\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"2\">\n                    <Path>F:\\viostor\\2k16\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"3\">\n                    <Path>F:\\NetKVM\\2k16\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"4\">\n                    <Path>F:\\Balloon\\2k16\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"5\">\n                    <Path>F:\\pvpanic\\2k16\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"6\">\n                    <Path>F:\\qemupciserial\\2k16\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"7\">\n                    <Path>F:\\qxldod\\2k16\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"8\">\n                    <Path>F:\\vioinput\\2k16\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"9\">\n                    <Path>F:\\viorng\\2k16\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"10\">\n                    <Path>F:\\vioscsi\\2k16\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"11\">\n                    <Path>F:\\vioserial\\2k16\\amd64</Path>\n                </PathAndCredentials>\n            </DriverPaths>\n        </component>\n\n        <component name=\"Microsoft-Windows-International-Core-WinPE\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <SetupUILanguage>\n                <UILanguage>en-US</UILanguage>\n            </SetupUILanguage>\n            <InputLocale>fr-FR</InputLocale>\n            <SystemLocale>en-US</SystemLocale>\n            <UILanguage>en-US</UILanguage>\n            <UILanguageFallback>fr-FR</UILanguageFallback>\n            <UserLocale>en-US</UserLocale>\n        </component>\n        <component name=\"Microsoft-Windows-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <DiskConfiguration>\n                <Disk wcm:action=\"add\">\n                    <CreatePartitions>\n                        <CreatePartition wcm:action=\"add\">\n                            <Order>1</Order>\n                            <Type>Primary</Type>\n                            <Extend>true</Extend>\n                        </CreatePartition>\n                    </CreatePartitions>\n                    <ModifyPartitions>\n                        <ModifyPartition wcm:action=\"add\">\n                            <Extend>false</Extend>\n                            <Format>NTFS</Format>\n                            <Letter>C</Letter>\n                            <Order>1</Order>\n                            <PartitionID>1</PartitionID>\n                            <Label>Windows 2016</Label>\n                        </ModifyPartition>\n                    </ModifyPartitions>\n                    <DiskID>0</DiskID>\n                    <WillWipeDisk>true</WillWipeDisk>\n                </Disk>\n                <WillShowUI>OnError</WillShowUI>\n            </DiskConfiguration>\n            <ImageInstall>\n                <OSImage>\n                    <InstallFrom>\n                        <MetaData wcm:action=\"add\">\n                            <Key>/IMAGE/NAME</Key>\n                            <Value>Windows Server 2016 SERVERSTANDARD</Value>\n                        </MetaData>\n                    </InstallFrom>\n                    <InstallTo>\n                        <DiskID>0</DiskID>\n                        <PartitionID>1</PartitionID>\n                    </InstallTo>\n                </OSImage>\n            </ImageInstall>\n            <UserData>\n                <!-- Product Key from https://www.microsoft.com/de-de/evalcenter/evaluate-windows-server-technical-preview?i=1 -->\n                <ProductKey>\n                    <!-- Do not uncomment the Key element if you are using trial ISOs -->\n                    <!-- You must uncomment the Key element (and optionally insert your own key) if you are using retail or volume license ISOs -->\n                    <!-- <Key>6XBNX-4JQGW-QX6QG-74P76-72V67</Key> -->\n                    <WillShowUI>OnError</WillShowUI>\n                </ProductKey>\n                <AcceptEula>true</AcceptEula>\n                <FullName>Vagrant</FullName>\n                <Organization>Vagrant</Organization>\n            </UserData>\n        </component>\n    </settings>\n    <settings pass=\"specialize\">\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <OEMInformation>\n                <HelpCustomized>false</HelpCustomized>\n            </OEMInformation>\n            <ComputerName>vagrant-2016</ComputerName>\n            <TimeZone>Romance Standard Time</TimeZone>\n            <RegisteredOwner/>\n        </component>\n        <component name=\"Microsoft-Windows-ServerManager-SvrMgrNc\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>\n        </component>\n        <component name=\"Microsoft-Windows-IE-ESC\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <IEHardenAdmin>false</IEHardenAdmin>\n            <IEHardenUser>false</IEHardenUser>\n        </component>\n        <component name=\"Microsoft-Windows-OutOfBoxExperience\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon>\n        </component>\n        <component name=\"Microsoft-Windows-Security-SPP-UX\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <SkipAutoActivation>true</SkipAutoActivation>\n        </component>\n    </settings>\n    <settings pass=\"oobeSystem\">\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <AutoLogon>\n                <Password>\n                    <Value>vagrant</Value>\n                    <PlainText>true</PlainText>\n                </Password>\n                <Enabled>true</Enabled>\n                <Username>vagrant</Username>\n            </AutoLogon>\n            <FirstLogonCommands>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                    <Description>Set Execution Policy 64 Bit</Description>\n                    <Order>1</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>C:\\Windows\\SysWOW64\\cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                    <Description>Set Execution Policy 32 Bit</Description>\n                    <Order>2</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c reg add \"HKLM\\System\\CurrentControlSet\\Control\\Network\\NewNetworkWindowOff\"</CommandLine>\n                    <Description>Network prompt</Description>\n                    <Order>3</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\fixnetwork.ps1</CommandLine>\n                    <Description>Fix public network</Description>\n                    <Order>4</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\disable-winrm.ps1</CommandLine>\n                    <Description>Disable WinRM</Description>\n                    <Order>5</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>6</Order>\n                    <Description>Show file extensions in Explorer</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>7</Order>\n                    <Description>Enable QuickEdit mode</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>8</Order>\n                    <Description>Show Run command in Start Menu</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>9</Order>\n                    <Description>Show Administrative Tools in Start Menu</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>10</Order>\n                    <Description>Zero Hibernation File</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>11</Order>\n                    <Description>Disable Hibernation Mode</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c wmic useraccount where \"name='vagrant'\" set PasswordExpires=FALSE</CommandLine>\n                    <Order>12</Order>\n                    <Description>Disable password expiration for vagrant user</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v DefaultPassword /t REG_SZ /d \"vagrant\" /f</CommandLine>\n                    <Order>13</Order>\n                    <Description>Enable AutoLogon</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v AutoAdminLogon /t REG_SZ /d 1 /f</CommandLine>\n                    <Order>14</Order>\n                    <Description>Enable AutoLogon</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <Order>15</Order>\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"netsh advfirewall firewall set rule group='Windows Remote Management' new enable=yes\"</CommandLine>\n                    <Description>Enable windows RDP</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <Order>16</Order>\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"F:\\guest-agent\\qemu-ga-x86_64.msi /quiet\"</CommandLine>\n                    <Description>Drivers install</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"G:\\Install-WMF3Hotfix.ps1\"</CommandLine>\n                    <Description>Install-WMF3Hotfix.ps1</Description>\n                    <Order>97</Order>\n                </SynchronousCommand>\n                <!-- no updates -->\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"G:\\ConfigureRemotingForAnsible.ps1\"</CommandLine>\n                    <Description>ConfigureRemotingForAnsible</Description>\n                    <Order>98</Order>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\enable-winrm.ps1</CommandLine>\n                    <Description>Enable WinRM</Description>\n                    <Order>99</Order>\n                </SynchronousCommand>\n                <!-- end no updates -->\n                <!-- WITH WINDOWS UPDATES \n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c G:\\microsoft-updates.bat</CommandLine>\n                    <Order>98</Order>\n                    <Description>Enable Microsoft Updates</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\disable-screensaver.ps1</CommandLine>\n                    <Description>Disable Screensaver</Description>\n                    <Order>99</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\win-updates.ps1</CommandLine>\n                    <Description>Install Windows Updates</Description>\n                    <Order>100</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                 END WITH WINDOWS UPDATES -->\n            </FirstLogonCommands>\n            <OOBE>\n                <HideEULAPage>true</HideEULAPage>\n                <HideLocalAccountScreen>true</HideLocalAccountScreen>\n                <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>\n                <HideOnlineAccountScreens>true</HideOnlineAccountScreens>\n                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\n                <NetworkLocation>Home</NetworkLocation>\n                <ProtectYourPC>1</ProtectYourPC>\n            </OOBE>\n            <UserAccounts>\n                <AdministratorPassword>\n                    <Value>vagrant</Value>\n                    <PlainText>true</PlainText>\n                </AdministratorPassword>\n                <LocalAccounts>\n                    <LocalAccount wcm:action=\"add\">\n                        <Password>\n                            <Value>vagrant</Value>\n                            <PlainText>true</PlainText>\n                        </Password>\n                        <Group>administrators</Group>\n                        <DisplayName>Vagrant</DisplayName>\n                        <Name>vagrant</Name>\n                        <Description>Vagrant User</Description>\n                    </LocalAccount>\n                </LocalAccounts>\n            </UserAccounts>\n            <RegisteredOwner />\n        </component>\n    </settings>\n    <settings pass=\"offlineServicing\">\n        <component name=\"Microsoft-Windows-LUA-Settings\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <EnableLUA>false</EnableLUA>\n        </component>\n    </settings>\n    <cpi:offlineImage cpi:source=\"wim:c:/wim/install.wim#Windows Server 2012 R2 SERVERSTANDARD\" xmlns:cpi=\"urn:schemas-microsoft-com:cpi\" />\n</unattend>\n"
  },
  {
    "path": "packer/proxmox/answer_files/2019_proxmox_cloudinit/Autounattend.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\n    <settings pass=\"windowsPE\">\n        <component name=\"Microsoft-Windows-PnpCustomizationsWinPE\"\n            publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\"\n            versionScope=\"nonSxS\" processorArchitecture=\"amd64\"\n            xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\">\n\n            <!--\n                 This makes the VirtIO drivers available to Windows, assuming that\n                 the VirtIO driver disk at https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso\n                 (see https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html#virtio-win-direct-downloads)\n                 is available as drive F:\n            -->\n            <DriverPaths>\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"2\">\n                    <Path>F:\\viostor\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"3\">\n                    <Path>F:\\NetKVM\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"4\">\n                    <Path>F:\\Balloon\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"5\">\n                    <Path>F:\\pvpanic\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"6\">\n                    <Path>F:\\qemupciserial\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"7\">\n                    <Path>F:\\qxldod\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"8\">\n                    <Path>F:\\vioinput\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"9\">\n                    <Path>F:\\viorng\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"10\">\n                    <Path>F:\\vioscsi\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"11\">\n                    <Path>F:\\vioserial\\2k19\\amd64</Path>\n                </PathAndCredentials>\n            </DriverPaths>\n        </component>\n        <component name=\"Microsoft-Windows-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <DiskConfiguration>\n                <Disk wcm:action=\"add\">\n                    <CreatePartitions>\n                        <CreatePartition wcm:action=\"add\">\n                            <Order>1</Order>\n                            <Type>Primary</Type>\n                            <Extend>true</Extend>\n                        </CreatePartition>\n                    </CreatePartitions>\n                    <ModifyPartitions>\n                        <ModifyPartition wcm:action=\"add\">\n                            <Extend>false</Extend>\n                            <Format>NTFS</Format>\n                            <Letter>C</Letter>\n                            <Order>1</Order>\n                            <PartitionID>1</PartitionID>\n                            <Label>Windows 2019</Label>\n                        </ModifyPartition>\n                    </ModifyPartitions>\n                    <DiskID>0</DiskID>\n                    <WillWipeDisk>true</WillWipeDisk>\n                </Disk>\n                <WillShowUI>OnError</WillShowUI>\n            </DiskConfiguration>\n            <ImageInstall>\n                <OSImage>\n                    <InstallFrom>\n                        <MetaData wcm:action=\"add\">\n                            <Key>/IMAGE/NAME</Key>\n                            <Value>Windows Server 2019 SERVERDATACENTER</Value>\n                        </MetaData>\n                    </InstallFrom>\n                    <InstallTo>\n                        <DiskID>0</DiskID>\n                        <PartitionID>1</PartitionID>\n                    </InstallTo>\n                </OSImage>\n            </ImageInstall>\n            <UserData>\n                <!-- Product Key from https://www.microsoft.com/de-de/evalcenter/evaluate-windows-server-technical-preview?i=1 -->\n                <ProductKey>\n                    <!-- Do not uncomment the Key element if you are using trial ISOs -->\n                    <!-- You must uncomment the Key element (and optionally insert your own key) if you are using retail or volume license ISOs -->\n                    <!-- <Key>6XBNX-4JQGW-QX6QG-74P76-72V67</Key> -->\n                    <WillShowUI>OnError</WillShowUI>\n                </ProductKey>\n                <AcceptEula>true</AcceptEula>\n                <FullName>Vagrant</FullName>\n                <Organization>Vagrant</Organization>\n            </UserData>\n        </component>\n        <component name=\"Microsoft-Windows-International-Core-WinPE\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <SetupUILanguage>\n                <UILanguage>en-US</UILanguage>\n            </SetupUILanguage>\n            <InputLocale>fr-FR</InputLocale>\n            <SystemLocale>en-US</SystemLocale>\n            <UILanguage>en-US</UILanguage>\n            <UILanguageFallback>fr-FR</UILanguageFallback>\n            <UserLocale>en-US</UserLocale>\n        </component>\n    </settings>\n    <settings pass=\"specialize\">\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <OEMInformation>\n                <HelpCustomized>false</HelpCustomized>\n            </OEMInformation>\n            <ComputerName>vagrant-2019</ComputerName>\n            <TimeZone>Romance Standard Time</TimeZone>\n            <RegisteredOwner/>\n        </component>\n        <component name=\"Microsoft-Windows-ServerManager-SvrMgrNc\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>\n        </component>\n        <component name=\"Microsoft-Windows-IE-ESC\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <IEHardenAdmin>false</IEHardenAdmin>\n            <IEHardenUser>false</IEHardenUser>\n        </component>\n        <component name=\"Microsoft-Windows-OutOfBoxExperience\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon>\n        </component>\n        <component name=\"Microsoft-Windows-Security-SPP-UX\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <SkipAutoActivation>true</SkipAutoActivation>\n        </component>\n    </settings>\n    <settings pass=\"oobeSystem\">\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <AutoLogon>\n                <Password>\n                    <Value>vagrant</Value>\n                    <PlainText>true</PlainText>\n                </Password>\n                <Enabled>true</Enabled>\n                <Username>vagrant</Username>\n            </AutoLogon>\n            <FirstLogonCommands>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                    <Description>Set Execution Policy 64 Bit</Description>\n                    <Order>1</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>C:\\Windows\\SysWOW64\\cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                    <Description>Set Execution Policy 32 Bit</Description>\n                    <Order>2</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c reg add \"HKLM\\System\\CurrentControlSet\\Control\\Network\\NewNetworkWindowOff\"</CommandLine>\n                    <Description>Network prompt</Description>\n                    <Order>3</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\fixnetwork.ps1</CommandLine>\n                    <Description>Fix public network</Description>\n                    <Order>4</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\disable-winrm.ps1</CommandLine>\n                    <Description>Disable WinRM</Description>\n                    <Order>5</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>6</Order>\n                    <Description>Show file extensions in Explorer</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>7</Order>\n                    <Description>Enable QuickEdit mode</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>8</Order>\n                    <Description>Show Run command in Start Menu</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>9</Order>\n                    <Description>Show Administrative Tools in Start Menu</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>10</Order>\n                    <Description>Zero Hibernation File</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>11</Order>\n                    <Description>Disable Hibernation Mode</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c wmic useraccount where \"name='vagrant'\" set PasswordExpires=FALSE</CommandLine>\n                    <Order>12</Order>\n                    <Description>Disable password expiration for vagrant user</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v DefaultPassword /t REG_SZ /d \"vagrant\" /f</CommandLine>\n                    <Order>13</Order>\n                    <Description>Enable AutoLogon</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v AutoAdminLogon /t REG_SZ /d 1 /f</CommandLine>\n                    <Order>14</Order>\n                    <Description>Enable AutoLogon</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <Order>15</Order>\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"netsh advfirewall firewall set rule group='Windows Remote Management' new enable=yes\"</CommandLine>\n                    <Description>Enable windows RDP</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <Order>16</Order>\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"F:\\guest-agent\\qemu-ga-x86_64.msi /quiet\"</CommandLine>\n                    <Description>Drivers install</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"G:\\Install-WMF3Hotfix.ps1\"</CommandLine>\n                    <Description>Install-WMF3Hotfix.ps1</Description>\n                    <Order>97</Order>\n                </SynchronousCommand>\n                <!-- no updates -->\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"G:\\ConfigureRemotingForAnsible.ps1\"</CommandLine>\n                    <Description>ConfigureRemotingForAnsible</Description>\n                    <Order>98</Order>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\enable-winrm.ps1</CommandLine>\n                    <Description>Enable WinRM</Description>\n                    <Order>99</Order>\n                </SynchronousCommand>\n                <!-- end no update -->\n                <!-- WITH WINDOWS UPDATES \n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c G:\\microsoft-updates.bat</CommandLine>\n                    <Order>98</Order>\n                    <Description>Enable Microsoft Updates</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\disable-screensaver.ps1</CommandLine>\n                    <Description>Disable Screensaver</Description>\n                    <Order>99</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\win-updates.ps1</CommandLine>\n                    <Description>Install Windows Updates</Description>\n                    <Order>100</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                 END WITH WINDOWS UPDATES -->\n            </FirstLogonCommands>\n            <OOBE>\n                <HideEULAPage>true</HideEULAPage>\n                <HideLocalAccountScreen>true</HideLocalAccountScreen>\n                <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>\n                <HideOnlineAccountScreens>true</HideOnlineAccountScreens>\n                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\n                <NetworkLocation>Home</NetworkLocation>\n                <ProtectYourPC>1</ProtectYourPC>\n            </OOBE>\n            <UserAccounts>\n                <AdministratorPassword>\n                    <Value>vagrant</Value>\n                    <PlainText>true</PlainText>\n                </AdministratorPassword>\n                <LocalAccounts>\n                    <LocalAccount wcm:action=\"add\">\n                        <Password>\n                            <Value>vagrant</Value>\n                            <PlainText>true</PlainText>\n                        </Password>\n                        <Group>administrators</Group>\n                        <DisplayName>Vagrant</DisplayName>\n                        <Name>vagrant</Name>\n                        <Description>Vagrant User</Description>\n                    </LocalAccount>\n                </LocalAccounts>\n            </UserAccounts>\n            <RegisteredOwner />\n        </component>\n    </settings>\n    <settings pass=\"offlineServicing\">\n        <component name=\"Microsoft-Windows-LUA-Settings\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <EnableLUA>false</EnableLUA>\n        </component>\n    </settings>\n    <cpi:offlineImage cpi:source=\"wim:c:/wim/install.wim#Windows Server 2012 R2 SERVERSTANDARD\" xmlns:cpi=\"urn:schemas-microsoft-com:cpi\" />\n</unattend>\n"
  },
  {
    "path": "packer/proxmox/answer_files/2019_proxmox_cloudinit_uptodate/Autounattend.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\n    <settings pass=\"windowsPE\">\n        <component name=\"Microsoft-Windows-PnpCustomizationsWinPE\"\n            publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\"\n            versionScope=\"nonSxS\" processorArchitecture=\"amd64\"\n            xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\">\n\n            <!--\n                 This makes the VirtIO drivers available to Windows, assuming that\n                 the VirtIO driver disk at https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso\n                 (see https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html#virtio-win-direct-downloads)\n                 is available as drive F:\n            -->\n            <DriverPaths>\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"2\">\n                    <Path>F:\\viostor\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"3\">\n                    <Path>F:\\NetKVM\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"4\">\n                    <Path>F:\\Balloon\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"5\">\n                    <Path>F:\\pvpanic\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"6\">\n                    <Path>F:\\qemupciserial\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"7\">\n                    <Path>F:\\qxldod\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"8\">\n                    <Path>F:\\vioinput\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"9\">\n                    <Path>F:\\viorng\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"10\">\n                    <Path>F:\\vioscsi\\2k19\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"11\">\n                    <Path>F:\\vioserial\\2k19\\amd64</Path>\n                </PathAndCredentials>\n            </DriverPaths>\n        </component>\n        <component name=\"Microsoft-Windows-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <DiskConfiguration>\n                <Disk wcm:action=\"add\">\n                    <CreatePartitions>\n                        <CreatePartition wcm:action=\"add\">\n                            <Order>1</Order>\n                            <Type>Primary</Type>\n                            <Extend>true</Extend>\n                        </CreatePartition>\n                    </CreatePartitions>\n                    <ModifyPartitions>\n                        <ModifyPartition wcm:action=\"add\">\n                            <Extend>false</Extend>\n                            <Format>NTFS</Format>\n                            <Letter>C</Letter>\n                            <Order>1</Order>\n                            <PartitionID>1</PartitionID>\n                            <Label>Windows 2019</Label>\n                        </ModifyPartition>\n                    </ModifyPartitions>\n                    <DiskID>0</DiskID>\n                    <WillWipeDisk>true</WillWipeDisk>\n                </Disk>\n                <WillShowUI>OnError</WillShowUI>\n            </DiskConfiguration>\n            <ImageInstall>\n                <OSImage>\n                    <InstallFrom>\n                        <MetaData wcm:action=\"add\">\n                            <Key>/IMAGE/NAME</Key>\n                            <Value>Windows Server 2019 SERVERDATACENTER</Value>\n                        </MetaData>\n                    </InstallFrom>\n                    <InstallTo>\n                        <DiskID>0</DiskID>\n                        <PartitionID>1</PartitionID>\n                    </InstallTo>\n                </OSImage>\n            </ImageInstall>\n            <UserData>\n                <!-- Product Key from https://www.microsoft.com/de-de/evalcenter/evaluate-windows-server-technical-preview?i=1 -->\n                <ProductKey>\n                    <!-- Do not uncomment the Key element if you are using trial ISOs -->\n                    <!-- You must uncomment the Key element (and optionally insert your own key) if you are using retail or volume license ISOs -->\n                    <!-- <Key>6XBNX-4JQGW-QX6QG-74P76-72V67</Key> -->\n                    <WillShowUI>OnError</WillShowUI>\n                </ProductKey>\n                <AcceptEula>true</AcceptEula>\n                <FullName>Vagrant</FullName>\n                <Organization>Vagrant</Organization>\n            </UserData>\n        </component>\n        <component name=\"Microsoft-Windows-International-Core-WinPE\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <SetupUILanguage>\n                <UILanguage>en-US</UILanguage>\n            </SetupUILanguage>\n            <InputLocale>fr-FR</InputLocale>\n            <SystemLocale>en-US</SystemLocale>\n            <UILanguage>en-US</UILanguage>\n            <UILanguageFallback>fr-FR</UILanguageFallback>\n            <UserLocale>en-US</UserLocale>\n        </component>\n    </settings>\n    <settings pass=\"specialize\">\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <OEMInformation>\n                <HelpCustomized>false</HelpCustomized>\n            </OEMInformation>\n            <ComputerName>vagrant-2019</ComputerName>\n            <TimeZone>Romance Standard Time</TimeZone>\n            <RegisteredOwner/>\n        </component>\n        <component name=\"Microsoft-Windows-ServerManager-SvrMgrNc\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>\n        </component>\n        <component name=\"Microsoft-Windows-IE-ESC\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <IEHardenAdmin>false</IEHardenAdmin>\n            <IEHardenUser>false</IEHardenUser>\n        </component>\n        <component name=\"Microsoft-Windows-OutOfBoxExperience\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon>\n        </component>\n        <component name=\"Microsoft-Windows-Security-SPP-UX\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <SkipAutoActivation>true</SkipAutoActivation>\n        </component>\n    </settings>\n    <settings pass=\"oobeSystem\">\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <AutoLogon>\n                <Password>\n                    <Value>vagrant</Value>\n                    <PlainText>true</PlainText>\n                </Password>\n                <Enabled>true</Enabled>\n                <Username>vagrant</Username>\n            </AutoLogon>\n            <FirstLogonCommands>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                    <Description>Set Execution Policy 64 Bit</Description>\n                    <Order>1</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>C:\\Windows\\SysWOW64\\cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                    <Description>Set Execution Policy 32 Bit</Description>\n                    <Order>2</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c reg add \"HKLM\\System\\CurrentControlSet\\Control\\Network\\NewNetworkWindowOff\"</CommandLine>\n                    <Description>Network prompt</Description>\n                    <Order>3</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\fixnetwork.ps1</CommandLine>\n                    <Description>Fix public network</Description>\n                    <Order>4</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\disable-winrm.ps1</CommandLine>\n                    <Description>Disable WinRM</Description>\n                    <Order>5</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>6</Order>\n                    <Description>Show file extensions in Explorer</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>7</Order>\n                    <Description>Enable QuickEdit mode</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>8</Order>\n                    <Description>Show Run command in Start Menu</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>9</Order>\n                    <Description>Show Administrative Tools in Start Menu</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>10</Order>\n                    <Description>Zero Hibernation File</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>11</Order>\n                    <Description>Disable Hibernation Mode</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c wmic useraccount where \"name='vagrant'\" set PasswordExpires=FALSE</CommandLine>\n                    <Order>12</Order>\n                    <Description>Disable password expiration for vagrant user</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v DefaultPassword /t REG_SZ /d \"vagrant\" /f</CommandLine>\n                    <Order>13</Order>\n                    <Description>Enable AutoLogon</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v AutoAdminLogon /t REG_SZ /d 1 /f</CommandLine>\n                    <Order>14</Order>\n                    <Description>Enable AutoLogon</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <Order>15</Order>\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"netsh advfirewall firewall set rule group='Windows Remote Management' new enable=yes\"</CommandLine>\n                    <Description>Enable windows RDP</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <Order>16</Order>\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"F:\\guest-agent\\qemu-ga-x86_64.msi /quiet\"</CommandLine>\n                    <Description>Drivers install</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"G:\\Install-WMF3Hotfix.ps1\"</CommandLine>\n                    <Description>Install-WMF3Hotfix.ps1</Description>\n                    <Order>97</Order>\n                </SynchronousCommand>\n                <!-- no updates \n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command \"G:\\ConfigureRemotingForAnsible.ps1\"</CommandLine>\n                    <Description>ConfigureRemotingForAnsible</Description>\n                    <Order>98</Order>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\enable-winrm.ps1</CommandLine>\n                    <Description>Enable WinRM</Description>\n                    <Order>99</Order>\n                </SynchronousCommand>\n                 end no update -->\n                <!-- WITH WINDOWS UPDATES -->\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c G:\\microsoft-updates.bat</CommandLine>\n                    <Order>98</Order>\n                    <Description>Enable Microsoft Updates</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\disable-screensaver.ps1</CommandLine>\n                    <Description>Disable Screensaver</Description>\n                    <Order>99</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File G:\\win-updates.ps1</CommandLine>\n                    <Description>Install Windows Updates</Description>\n                    <Order>100</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <!-- END WITH WINDOWS UPDATES -->\n            </FirstLogonCommands>\n            <OOBE>\n                <HideEULAPage>true</HideEULAPage>\n                <HideLocalAccountScreen>true</HideLocalAccountScreen>\n                <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>\n                <HideOnlineAccountScreens>true</HideOnlineAccountScreens>\n                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\n                <NetworkLocation>Home</NetworkLocation>\n                <ProtectYourPC>1</ProtectYourPC>\n            </OOBE>\n            <UserAccounts>\n                <AdministratorPassword>\n                    <Value>vagrant</Value>\n                    <PlainText>true</PlainText>\n                </AdministratorPassword>\n                <LocalAccounts>\n                    <LocalAccount wcm:action=\"add\">\n                        <Password>\n                            <Value>vagrant</Value>\n                            <PlainText>true</PlainText>\n                        </Password>\n                        <Group>administrators</Group>\n                        <DisplayName>Vagrant</DisplayName>\n                        <Name>vagrant</Name>\n                        <Description>Vagrant User</Description>\n                    </LocalAccount>\n                </LocalAccounts>\n            </UserAccounts>\n            <RegisteredOwner />\n        </component>\n    </settings>\n    <settings pass=\"offlineServicing\">\n        <component name=\"Microsoft-Windows-LUA-Settings\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <EnableLUA>false</EnableLUA>\n        </component>\n    </settings>\n    <cpi:offlineImage cpi:source=\"wim:c:/wim/install.wim#Windows Server 2012 R2 SERVERSTANDARD\" xmlns:cpi=\"urn:schemas-microsoft-com:cpi\" />\n</unattend>\n"
  },
  {
    "path": "packer/proxmox/build_proxmox_iso.sh",
    "content": "#!/bin/bash\n\n# transform files into iso, because proxmox only accept iso and no floppy A:\\\n\necho \"[+] Build iso windows 10 with cloudinit\"\nmkisofs -J -l -R -V \"autounatend CD\" -iso-level 4 -o ./iso/Autounattend_windows10_cloudinit.iso answer_files/10_proxmox_cloudinit\nsha_win10=$(sha256sum ./iso/Autounattend_windows10_cloudinit.iso|cut -d ' ' -f1)\necho \"[+] update windows_10_22h2_proxmox_cloudinit.pkvars.hcl\"\nsed -i \"s/\\\"sha256:.*\\\"/\\\"sha256:$sha_win10\\\"/g\" windows_10_22h2_proxmox_cloudinit.pkvars.hcl\n\necho \"[+] Build iso windows 10 with cloudinit and update\"\nmkisofs -J -l -R -V \"autounatend CD\" -iso-level 4 -o ./iso/Autounattend_windows10_cloudinit_uptodate.iso answer_files/10_proxmox_cloudinit_uptodate\nsha_win10=$(sha256sum ./iso/Autounattend_windows10_cloudinit_uptodate.iso|cut -d ' ' -f1)\necho \"[+] update windows_10_22h2_proxmox_cloudinit_uptodate.pkvars.hcl\"\nsed -i \"s/\\\"sha256:.*\\\"/\\\"sha256:$sha_win10\\\"/g\" windows_10_22h2_proxmox_cloudinit_uptodate.pkvars.hcl\n\necho \"[+] Build iso winserver2016 with cloudinit\"\nmkisofs -J -l -R -V \"autounatend CD\" -iso-level 4 -o ./iso/Autounattend_winserver2016_cloudinit.iso answer_files/2016_proxmox_cloudinit\nsha_winserv2016=$(sha256sum ./iso/Autounattend_winserver2016_cloudinit.iso|cut -d ' ' -f1)\necho \"[+] update windows_server2016_proxmox_cloudinit.pkvars.hcl\"\nsed -i \"s/\\\"sha256:.*\\\"/\\\"sha256:$sha_winserv2016\\\"/g\" windows_server2016_proxmox_cloudinit.pkvars.hcl\n\necho \"[+] Build iso winserver2019 with cloudinit\"\nmkisofs -J -l -R -V \"autounatend CD\" -iso-level 4 -o ./iso/Autounattend_winserver2019_cloudinit.iso answer_files/2019_proxmox_cloudinit\nsha_winserv2019=$(sha256sum ./iso/Autounattend_winserver2019_cloudinit.iso|cut -d ' ' -f1)\necho \"[+] update windows_server2019_proxmox_cloudinit.pkvars.hcl\"\nsed -i \"s/\\\"sha256:.*\\\"/\\\"sha256:$sha_winserv2019\\\"/g\" windows_server2019_proxmox_cloudinit.pkvars.hcl\n\necho \"[+] Build iso winserver2019 with cloudinit and update\"\nmkisofs -J -l -R -V \"autounatend CD\" -iso-level 4 -o ./iso/Autounattend_winserver2019_cloudinit_uptodate.iso answer_files/2019_proxmox_cloudinit_uptodate\nsha_winserv2019_update=$(sha256sum ./iso/Autounattend_winserver2019_cloudinit_uptodate.iso|cut -d ' ' -f1)\necho \"[+] update windows_server2019_proxmox_cloudinit_uptodate.pkvars.hcl\"\nsed -i \"s/\\\"sha256:.*\\\"/\\\"sha256:$sha_winserv2019_update\\\"/g\" windows_server2019_proxmox_cloudinit_uptodate.pkvars.hcl\n\necho \"[+] Build iso windows 11 with cloudinit and update\"\nmkisofs -J -l -R -V \"autounatend CD\" -iso-level 4 -o ./iso/Autounattend_windows11_cloudinit_uptodate.iso answer_files/11_proxmox_cloudinit_uptodate\nsha_win10=$(sha256sum ./iso/Autounattend_windows11_cloudinit_uptodate.iso|cut -d ' ' -f1)\necho \"[+] update windows_11_23h2_proxmox_cloudinit_uptodate.pkvars.hcl\"\nsed -i \"s/\\\"sha256:.*\\\"/\\\"sha256:$sha_win10\\\"/g\" windows_11_23h2_proxmox_cloudinit_uptodate.pkvars.hcl\n\necho \"[+] Build iso for scripts\"\nmkisofs -J -l -R -V \"scripts CD\" -iso-level 4 -o ./iso/scripts_withcloudinit.iso scripts\n# echo \"scripts_withcloudinit.iso\"\n# sha256sum ./iso/scripts_withcloudinit.iso\n"
  },
  {
    "path": "packer/proxmox/config.auto.pkrvars.hcl.template",
    "content": "proxmox_url             = \"https://192.168.1.1:8006/api2/json\"\nproxmox_username        = \"infra_as_code@pve\"\nproxmox_password        = \"CHANGEME\"\nproxmox_skip_tls_verify = \"true\"\nproxmox_node            = \"proxmox-goad\"\nproxmox_pool            = \"Templates\"\nproxmox_iso_storage     = \"local\"\nproxmox_vm_storage      = \"local-lvm\"\n"
  },
  {
    "path": "packer/proxmox/iso/.gitignore",
    "content": "*.iso"
  },
  {
    "path": "packer/proxmox/packer.json.pkr.hcl",
    "content": "\npacker {\n  required_plugins {\n    proxmox = {\n      version = \">= 1.1.2\"\n      source  = \"github.com/hashicorp/proxmox\"\n    }\n  }\n}\n\nsource \"proxmox-iso\" \"windows\" {\n  additional_iso_files {\n    device           = \"sata3\"\n    iso_checksum     = \"${var.autounattend_checksum}\"\n    iso_storage_pool = \"local\"\n    iso_url          = \"${var.autounattend_iso}\"\n    unmount          = true\n  }\n  additional_iso_files {\n    device   = \"sata4\"\n    iso_file = \"local:iso/virtio-win.iso\"\n    unmount  = true\n  }\n  additional_iso_files {\n    device   = \"sata5\"\n    iso_file = \"local:iso/scripts_withcloudinit.iso\"\n    unmount  = true\n  }\n  cloud_init              = true\n  cloud_init_storage_pool = \"${var.proxmox_iso_storage}\"\n  communicator            = \"winrm\"\n  cores                   = \"${var.vm_cpu_cores}\"\n  disks {\n    disk_size         = \"${var.vm_disk_size}\"\n    format            = \"${var.vm_disk_format}\"\n    storage_pool      = \"${var.proxmox_vm_storage}\"\n    type              = \"sata\"\n  }\n  insecure_skip_tls_verify = \"${var.proxmox_skip_tls_verify}\"\n  iso_file                 = \"${var.iso_file}\"\n  memory                   = \"${var.vm_memory}\"\n  network_adapters {\n    bridge = \"vmbr3\"\n    model  = \"virtio\"\n    vlan_tag = \"10\"\n  }\n  node                 = \"${var.proxmox_node}\"\n  os                   = \"${var.os}\"\n  password             = \"${var.proxmox_password}\"\n  pool                 = \"${var.proxmox_pool}\"\n  proxmox_url          = \"${var.proxmox_url}\"\n  sockets              = \"${var.vm_sockets}\"\n  template_description = \"${var.template_description}\"\n  template_name        = \"${var.vm_name}\"\n  username             = \"${var.proxmox_username}\"\n  vm_name              = \"${var.vm_name}\"\n  winrm_insecure       = true\n  winrm_no_proxy       = true\n  winrm_password       = \"${var.winrm_password}\"\n  winrm_timeout        = \"120m\"\n  winrm_use_ssl        = true\n  winrm_username       = \"${var.winrm_username}\"\n  task_timeout         = \"40m\"\n}\n\nbuild {\n  sources = [\"source.proxmox-iso.windows\"]\n\n  provisioner \"powershell\" {\n    elevated_password = \"vagrant\"\n    elevated_user     = \"vagrant\"\n    scripts           = [\"${path.root}/scripts/sysprep/cloudbase-init.ps1\"]\n  }\n\n  provisioner \"powershell\" {\n    elevated_password = \"vagrant\"\n    elevated_user     = \"vagrant\"\n    pause_before      = \"1m0s\"\n    scripts           = [\"${path.root}/scripts/sysprep/cloudbase-init-p2.ps1\"]\n  }\n\n}\n"
  },
  {
    "path": "packer/proxmox/scripts/ConfigureRemotingForAnsible.ps1",
    "content": "#Requires -Version 3.0\n\n# Configure a Windows host for remote management with Ansible\n# -----------------------------------------------------------\n#\n# This script checks the current WinRM (PS Remoting) configuration and makes\n# the necessary changes to allow Ansible to connect, authenticate and\n# execute PowerShell commands.\n#\n# All events are logged to the Windows EventLog, useful for unattended runs.\n#\n# Use option -Verbose in order to see the verbose output messages.\n#\n# Use option -CertValidityDays to specify how long this certificate is valid\n# starting from today. So you would specify -CertValidityDays 3650 to get\n# a 10-year valid certificate.\n#\n# Use option -ForceNewSSLCert if the system has been SysPreped and a new\n# SSL Certificate must be forced on the WinRM Listener when re-running this\n# script. This is necessary when a new SID and CN name is created.\n#\n# Use option -EnableCredSSP to enable CredSSP as an authentication option.\n#\n# Use option -DisableBasicAuth to disable basic authentication.\n#\n# Use option -SkipNetworkProfileCheck to skip the network profile check.\n# Without specifying this the script will only run if the device's interfaces\n# are in DOMAIN or PRIVATE zones.  Provide this switch if you want to enable\n# WinRM on a device with an interface in PUBLIC zone.\n#\n# Use option -SubjectName to specify the CN name of the certificate. This\n# defaults to the system's hostname and generally should not be specified.\n\n# Written by Trond Hindenes <trond@hindenes.com>\n# Updated by Chris Church <cchurch@ansible.com>\n# Updated by Michael Crilly <mike@autologic.cm>\n# Updated by Anton Ouzounov <Anton.Ouzounov@careerbuilder.com>\n# Updated by Nicolas Simond <contact@nicolas-simond.com>\n# Updated by Dag Wieërs <dag@wieers.com>\n# Updated by Jordan Borean <jborean93@gmail.com>\n# Updated by Erwan Quélin <erwan.quelin@gmail.com>\n# Updated by David Norman <david@dkn.email>\n#\n# Version 1.0 - 2014-07-06\n# Version 1.1 - 2014-11-11\n# Version 1.2 - 2015-05-15\n# Version 1.3 - 2016-04-04\n# Version 1.4 - 2017-01-05\n# Version 1.5 - 2017-02-09\n# Version 1.6 - 2017-04-18\n# Version 1.7 - 2017-11-23\n# Version 1.8 - 2018-02-23\n# Version 1.9 - 2018-09-21\n\n# Support -Verbose option\n[CmdletBinding()]\n\nParam (\n    [string]$SubjectName = $env:COMPUTERNAME,\n    [int]$CertValidityDays = 1095,\n    [switch]$SkipNetworkProfileCheck,\n    $CreateSelfSignedCert = $true,\n    [switch]$ForceNewSSLCert,\n    [switch]$GlobalHttpFirewallAccess,\n    [switch]$DisableBasicAuth = $false,\n    [switch]$EnableCredSSP\n)\n\nFunction Write-Log\n{\n    $Message = $args[0]\n    Write-EventLog -LogName Application -Source $EventSource -EntryType Information -EventId 1 -Message $Message\n}\n\nFunction Write-VerboseLog\n{\n    $Message = $args[0]\n    Write-Verbose $Message\n    Write-Log $Message\n}\n\nFunction Write-HostLog\n{\n    $Message = $args[0]\n    Write-Output $Message\n    Write-Log $Message\n}\n\nFunction New-LegacySelfSignedCert\n{\n    Param (\n        [string]$SubjectName,\n        [int]$ValidDays = 1095\n    )\n\n    $hostnonFQDN = $env:computerName\n    $hostFQDN = [System.Net.Dns]::GetHostByName(($env:computerName)).Hostname\n    $SignatureAlgorithm = \"SHA256\"\n\n    $name = New-Object -COM \"X509Enrollment.CX500DistinguishedName.1\"\n    $name.Encode(\"CN=$SubjectName\", 0)\n\n    $key = New-Object -COM \"X509Enrollment.CX509PrivateKey.1\"\n    $key.ProviderName = \"Microsoft Enhanced RSA and AES Cryptographic Provider\"\n    $key.KeySpec = 1\n    $key.Length = 4096\n    $key.SecurityDescriptor = \"D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)\"\n    $key.MachineContext = 1\n    $key.Create()\n\n    $serverauthoid = New-Object -COM \"X509Enrollment.CObjectId.1\"\n    $serverauthoid.InitializeFromValue(\"1.3.6.1.5.5.7.3.1\")\n    $ekuoids = New-Object -COM \"X509Enrollment.CObjectIds.1\"\n    $ekuoids.Add($serverauthoid)\n    $ekuext = New-Object -COM \"X509Enrollment.CX509ExtensionEnhancedKeyUsage.1\"\n    $ekuext.InitializeEncode($ekuoids)\n\n    $cert = New-Object -COM \"X509Enrollment.CX509CertificateRequestCertificate.1\"\n    $cert.InitializeFromPrivateKey(2, $key, \"\")\n    $cert.Subject = $name\n    $cert.Issuer = $cert.Subject\n    $cert.NotBefore = (Get-Date).AddDays(-1)\n    $cert.NotAfter = $cert.NotBefore.AddDays($ValidDays)\n\n    $SigOID = New-Object -ComObject X509Enrollment.CObjectId\n    $SigOID.InitializeFromValue(([Security.Cryptography.Oid]$SignatureAlgorithm).Value)\n\n    [string[]] $AlternativeName  += $hostnonFQDN\n    $AlternativeName += $hostFQDN\n    $IAlternativeNames = New-Object -ComObject X509Enrollment.CAlternativeNames\n\n    foreach ($AN in $AlternativeName)\n    {\n        $AltName = New-Object -ComObject X509Enrollment.CAlternativeName\n        $AltName.InitializeFromString(0x3,$AN)\n        $IAlternativeNames.Add($AltName)\n    }\n\n    $SubjectAlternativeName = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames\n    $SubjectAlternativeName.InitializeEncode($IAlternativeNames)\n\n    [String[]]$KeyUsage = (\"DigitalSignature\", \"KeyEncipherment\")\n    $KeyUsageObj = New-Object -ComObject X509Enrollment.CX509ExtensionKeyUsage\n    $KeyUsageObj.InitializeEncode([int][Security.Cryptography.X509Certificates.X509KeyUsageFlags]($KeyUsage))\n    $KeyUsageObj.Critical = $true\n\n    $cert.X509Extensions.Add($KeyUsageObj)\n    $cert.X509Extensions.Add($ekuext)\n    $cert.SignatureInformation.HashAlgorithm = $SigOID\n    $CERT.X509Extensions.Add($SubjectAlternativeName)\n    $cert.Encode()\n\n    $enrollment = New-Object -COM \"X509Enrollment.CX509Enrollment.1\"\n    $enrollment.InitializeFromRequest($cert)\n    $certdata = $enrollment.CreateRequest(0)\n    $enrollment.InstallResponse(2, $certdata, 0, \"\")\n\n    # extract/return the thumbprint from the generated cert\n    $parsed_cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2\n    $parsed_cert.Import([System.Text.Encoding]::UTF8.GetBytes($certdata))\n\n    return $parsed_cert.Thumbprint\n}\n\nFunction Enable-GlobalHttpFirewallAccess\n{\n    Write-Verbose \"Forcing global HTTP firewall access\"\n    # this is a fairly naive implementation; could be more sophisticated about rule matching/collapsing\n    $fw = New-Object -ComObject HNetCfg.FWPolicy2\n\n    # try to find/enable the default rule first\n    $add_rule = $false\n    $matching_rules = $fw.Rules | Where-Object  { $_.Name -eq \"Windows Remote Management (HTTP-In)\" }\n    $rule = $null\n    If ($matching_rules) {\n        If ($matching_rules -isnot [Array]) {\n            Write-Verbose \"Editing existing single HTTP firewall rule\"\n            $rule = $matching_rules\n        }\n        Else {\n            # try to find one with the All or Public profile first\n            Write-Verbose \"Found multiple existing HTTP firewall rules...\"\n            $rule = $matching_rules | ForEach-Object { $_.Profiles -band 4 }[0]\n\n            If (-not $rule -or $rule -is [Array]) {\n                Write-Verbose \"Editing an arbitrary single HTTP firewall rule (multiple existed)\"\n                # oh well, just pick the first one\n                $rule = $matching_rules[0]\n            }\n        }\n    }\n\n    If (-not $rule) {\n        Write-Verbose \"Creating a new HTTP firewall rule\"\n        $rule = New-Object -ComObject HNetCfg.FWRule\n        $rule.Name = \"Windows Remote Management (HTTP-In)\"\n        $rule.Description = \"Inbound rule for Windows Remote Management via WS-Management. [TCP 5985]\"\n        $add_rule = $true\n    }\n\n    $rule.Profiles = 0x7FFFFFFF\n    $rule.Protocol = 6\n    $rule.LocalPorts = 5985\n    $rule.RemotePorts = \"*\"\n    $rule.LocalAddresses = \"*\"\n    $rule.RemoteAddresses = \"*\"\n    $rule.Enabled = $true\n    $rule.Direction = 1\n    $rule.Action = 1\n    $rule.Grouping = \"Windows Remote Management\"\n\n    If ($add_rule) {\n        $fw.Rules.Add($rule)\n    }\n\n    Write-Verbose \"HTTP firewall rule $($rule.Name) updated\"\n}\n\n# Setup error handling.\nTrap\n{\n    $_\n    Exit 1\n}\n$ErrorActionPreference = \"Stop\"\n\n# Get the ID and security principal of the current user account\n$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()\n$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)\n\n# Get the security principal for the Administrator role\n$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator\n\n# Check to see if we are currently running \"as Administrator\"\nif (-Not $myWindowsPrincipal.IsInRole($adminRole))\n{\n    Write-Output \"ERROR: You need elevated Administrator privileges in order to run this script.\"\n    Write-Output \"       Start Windows PowerShell by using the Run as Administrator option.\"\n    Exit 2\n}\n\n$EventSource = $MyInvocation.MyCommand.Name\nIf (-Not $EventSource)\n{\n    $EventSource = \"Powershell CLI\"\n}\n\nIf ([System.Diagnostics.EventLog]::Exists('Application') -eq $False -or [System.Diagnostics.EventLog]::SourceExists($EventSource) -eq $False)\n{\n    New-EventLog -LogName Application -Source $EventSource\n}\n\n# Detect PowerShell version.\nIf ($PSVersionTable.PSVersion.Major -lt 3)\n{\n    Write-Log \"PowerShell version 3 or higher is required.\"\n    Throw \"PowerShell version 3 or higher is required.\"\n}\n\n# Find and start the WinRM service.\nWrite-Verbose \"Verifying WinRM service.\"\nIf (!(Get-Service \"WinRM\"))\n{\n    Write-Log \"Unable to find the WinRM service.\"\n    Throw \"Unable to find the WinRM service.\"\n}\nElseIf ((Get-Service \"WinRM\").Status -ne \"Running\")\n{\n    Write-Verbose \"Setting WinRM service to start automatically on boot.\"\n    Set-Service -Name \"WinRM\" -StartupType Automatic\n    Write-Log \"Set WinRM service to start automatically on boot.\"\n    Write-Verbose \"Starting WinRM service.\"\n    Start-Service -Name \"WinRM\" -ErrorAction Stop\n    Write-Log \"Started WinRM service.\"\n\n}\n\n# WinRM should be running; check that we have a PS session config.\nIf (!(Get-PSSessionConfiguration -Verbose:$false) -or (!(Get-ChildItem WSMan:\\localhost\\Listener)))\n{\n  If ($SkipNetworkProfileCheck) {\n    Write-Verbose \"Enabling PS Remoting without checking Network profile.\"\n    Enable-PSRemoting -SkipNetworkProfileCheck -Force -ErrorAction Stop\n    Write-Log \"Enabled PS Remoting without checking Network profile.\"\n  }\n  Else {\n    Write-Verbose \"Enabling PS Remoting.\"\n    Enable-PSRemoting -Force -ErrorAction Stop\n    Write-Log \"Enabled PS Remoting.\"\n  }\n}\nElse\n{\n    Write-Verbose \"PS Remoting is already enabled.\"\n}\n\n# Ensure LocalAccountTokenFilterPolicy is set to 1\n# https://github.com/ansible/ansible/issues/42978\n$token_path = \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\"\n$token_prop_name = \"LocalAccountTokenFilterPolicy\"\n$token_key = Get-Item -Path $token_path\n$token_value = $token_key.GetValue($token_prop_name, $null)\nif ($token_value -ne 1) {\n    Write-Verbose \"Setting LocalAccountTOkenFilterPolicy to 1\"\n    if ($null -ne $token_value) {\n        Remove-ItemProperty -Path $token_path -Name $token_prop_name\n    }\n    New-ItemProperty -Path $token_path -Name $token_prop_name -Value 1 -PropertyType DWORD > $null\n}\n\n# Make sure there is a SSL listener.\n$listeners = Get-ChildItem WSMan:\\localhost\\Listener\nIf (!($listeners | Where-Object {$_.Keys -like \"TRANSPORT=HTTPS\"}))\n{\n    # We cannot use New-SelfSignedCertificate on 2012R2 and earlier\n    $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays\n    Write-HostLog \"Self-signed SSL certificate generated; thumbprint: $thumbprint\"\n\n    # Create the hashtables of settings to be used.\n    $valueset = @{\n        Hostname = $SubjectName\n        CertificateThumbprint = $thumbprint\n    }\n\n    $selectorset = @{\n        Transport = \"HTTPS\"\n        Address = \"*\"\n    }\n\n    Write-Verbose \"Enabling SSL listener.\"\n    New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset\n    Write-Log \"Enabled SSL listener.\"\n}\nElse\n{\n    Write-Verbose \"SSL listener is already active.\"\n\n    # Force a new SSL cert on Listener if the $ForceNewSSLCert\n    If ($ForceNewSSLCert)\n    {\n\n        # We cannot use New-SelfSignedCertificate on 2012R2 and earlier\n        $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays\n        Write-HostLog \"Self-signed SSL certificate generated; thumbprint: $thumbprint\"\n\n        $valueset = @{\n            CertificateThumbprint = $thumbprint\n            Hostname = $SubjectName\n        }\n\n        # Delete the listener for SSL\n        $selectorset = @{\n            Address = \"*\"\n            Transport = \"HTTPS\"\n        }\n        Remove-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset\n\n        # Add new Listener with new SSL cert\n        New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset\n    }\n}\n\n# Check for basic authentication.\n$basicAuthSetting = Get-ChildItem WSMan:\\localhost\\Service\\Auth | Where-Object {$_.Name -eq \"Basic\"}\n\nIf ($DisableBasicAuth)\n{\n    If (($basicAuthSetting.Value) -eq $true)\n    {\n        Write-Verbose \"Disabling basic auth support.\"\n        Set-Item -Path \"WSMan:\\localhost\\Service\\Auth\\Basic\" -Value $false\n        Write-Log \"Disabled basic auth support.\"\n    }\n    Else\n    {\n        Write-Verbose \"Basic auth is already disabled.\"\n    }\n}\nElse\n{\n    If (($basicAuthSetting.Value) -eq $false)\n    {\n        Write-Verbose \"Enabling basic auth support.\"\n        Set-Item -Path \"WSMan:\\localhost\\Service\\Auth\\Basic\" -Value $true\n        Write-Log \"Enabled basic auth support.\"\n    }\n    Else\n    {\n        Write-Verbose \"Basic auth is already enabled.\"\n    }\n}\n\n# If EnableCredSSP if set to true\nIf ($EnableCredSSP)\n{\n    # Check for CredSSP authentication\n    $credsspAuthSetting = Get-ChildItem WSMan:\\localhost\\Service\\Auth | Where-Object {$_.Name -eq \"CredSSP\"}\n    If (($credsspAuthSetting.Value) -eq $false)\n    {\n        Write-Verbose \"Enabling CredSSP auth support.\"\n        Enable-WSManCredSSP -role server -Force\n        Write-Log \"Enabled CredSSP auth support.\"\n    }\n}\n\nIf ($GlobalHttpFirewallAccess) {\n    Enable-GlobalHttpFirewallAccess\n}\n\n# Configure firewall to allow WinRM HTTPS connections.\n$fwtest1 = netsh advfirewall firewall show rule name=\"Allow WinRM HTTPS\"\n$fwtest2 = netsh advfirewall firewall show rule name=\"Allow WinRM HTTPS\" profile=any\nIf ($fwtest1.count -lt 5)\n{\n    Write-Verbose \"Adding firewall rule to allow WinRM HTTPS.\"\n    netsh advfirewall firewall add rule profile=any name=\"Allow WinRM HTTPS\" dir=in localport=5986 protocol=TCP action=allow\n    Write-Log \"Added firewall rule to allow WinRM HTTPS.\"\n}\nElseIf (($fwtest1.count -ge 5) -and ($fwtest2.count -lt 5))\n{\n    Write-Verbose \"Updating firewall rule to allow WinRM HTTPS for any profile.\"\n    netsh advfirewall firewall set rule name=\"Allow WinRM HTTPS\" new profile=any\n    Write-Log \"Updated firewall rule to allow WinRM HTTPS for any profile.\"\n}\nElse\n{\n    Write-Verbose \"Firewall rule already exists to allow WinRM HTTPS.\"\n}\n\n# Test a remoting connection to localhost, which should work.\n$httpResult = Invoke-Command -ComputerName \"localhost\" -ScriptBlock {$env:COMPUTERNAME} -ErrorVariable httpError -ErrorAction SilentlyContinue\n$httpsOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck\n\n$httpsResult = New-PSSession -UseSSL -ComputerName \"localhost\" -SessionOption $httpsOptions -ErrorVariable httpsError -ErrorAction SilentlyContinue\n\nIf ($httpResult -and $httpsResult)\n{\n    Write-Verbose \"HTTP: Enabled | HTTPS: Enabled\"\n}\nElseIf ($httpsResult -and !$httpResult)\n{\n    Write-Verbose \"HTTP: Disabled | HTTPS: Enabled\"\n}\nElseIf ($httpResult -and !$httpsResult)\n{\n    Write-Verbose \"HTTP: Enabled | HTTPS: Disabled\"\n}\nElse\n{\n    Write-Log \"Unable to establish an HTTP or HTTPS remoting session.\"\n    Throw \"Unable to establish an HTTP or HTTPS remoting session.\"\n}\nWrite-VerboseLog \"PS Remoting has been successfully configured for Ansible.\"\n"
  },
  {
    "path": "packer/proxmox/scripts/Install-WMF3Hotfix.ps1",
    "content": "#Requires -Version 3.0\n<#PSScriptInfo\n.VERSION 1.0\n.GUID 6cf319d1-8c50-460b-99ee-71b11cf7270d\n.AUTHOR\n    Jordan Borean <jborean93@gmail.com>\n.COPYRIGHT\n    Jordan Borean 2017\n.TAGS\n    PowerShell,Ansible,WinRM,WMF,Hotfix\n.LICENSEURI https://github.com/jborean93/ansible-windows/blob/master/LICENSE\n.PROJECTURI https://github.com/jborean93/ansible-windows\n.RELEASENOTES\n    Version 1.0: 2017-09-27\n        Initial script created\n#>\n\n<#\n.DESCRIPTION\nThe script will install the WinRM hotfix KB2842230 which fixes the memory\nissues that occur when running over WinRM with WMF 3.0. \nThe script will;\n    1. Detect if running on PS version 3.0 and exit if it is not\n    2. Check if KB2842230 is already installed and exit if it is\n    3. Download the hotfix from Microsoft server's based on the OS version\n    4. Extract the .msu file from the downloaded hotfix\n    5. Install the .msu silently\n    6. Detect if a reboot is required and prompt whether the user wants to restart\n\nOnce the install is complete, if the install process returns an exit\ncode of 3010, it will ask the user whether to restart the computer now\nor whether it will be done later.\n\nSee https://github.com/jborean93/ansible-windows/tree/master/scripts for more\ndetails.\n.PARAMETER Verbose\n    [switch] - Whether to display Verbose logs on the console\n.EXAMPLE\n    powershell.exe -ExecutionPolicy ByPass -File Install-WMF3Hotfix.ps1\n.EXAMPLE\n    powershell.exe -ExecutionPolicy ByPass -File Install-WMF3Hotfix.ps1 -Verbose\n#>\n\n[CmdletBinding()]\nParam()\n\n$ErrorActionPreference = \"Stop\"\nif ($verbose) {\n    $VerbosePreference = \"Continue\"\n}\n\nFunction Run-Process($executable, $arguments) {\n    $process = New-Object -TypeName System.Diagnostics.Process\n    $psi = $process.StartInfo\n    $psi.FileName = $executable\n    $psi.Arguments = $arguments\n    Write-Verbose -Message \"starting new process '$executable $arguments'\"\n    $process.Start() | Out-Null\n\n    $process.WaitForExit() | Out-Null\n    $exit_code = $process.ExitCode\n    Write-Verbose -Message \"process completed with exit code '$exit_code'\"\n\n    return $exit_code\n}\n\nFunction Download-File($url, $path) {\n    Write-Verbose -Message \"downloading url '$url' to '$path'\"\n    $client = New-Object -TypeName System.Net.WebClient\n    $client.DownloadFile($url, $path)\n}\n\nFunction Extract-Zip($zip, $dest) {\n    Write-Verbose -Message \"extracting '$zip' to '$dest'\"\n    try {\n        Add-Type -AssemblyName System.IO.Compression.FileSystem > $null\n        $legacy = $false\n    } catch {\n        $legacy = $true\n    }\n\n    if ($legacy) {\n        $shell = New-Object -ComObject Shell.Application\n        $zip_src = $shell.NameSpace($zip)\n        $zip_dest = $shell.NameSpace($dest)\n        $zip_dest.CopyHere($zip_src.Items(), 1044)\n    } else {\n        [System.IO.Compression.ZipFile]::ExtractToDirectory($zip, $dest)\n    }\n}\n\n$tmp_dir = $env:temp\n$kb = \"KB2842230\"\nif ($PSVersionTable.PSVersion.Major -ne 3) {\n    Write-Verbose -Message \"$kb is only applicable with Powershell v3, no action required\"\n    exit 0\n}\n\n$hotfix_installed = Get-Hotfix -Id $kb -ErrorAction SilentlyContinue\nif ($hotfix_installed -ne $null) {\n    Write-Verbose -Message \"$kb is already installed\"\n    exit 0\n}\n\nif (-not (Test-Path -Path $tmp_dir)) {\n    New-Item -Path $tmp_dir -ItemType Directory > $null\n}\n$os_version = [Version](Get-Item -Path \"$env:SystemRoot\\System32\\kernel32.dll\").VersionInfo.ProductVersion\n$host_string = \"$($os_version.Major).$($os_version.Minor)-$($env:PROCESSOR_ARCHITECTURE)\"\nswitch($host_string) {\n    # These URLS point to the Ansible Core CI S3 bucket, MS no longer provide a link to Server 2008 so we need to\n    # rely on this URL. There are no guarantees this will stay up in the future.\n    \"6.0-x86\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/464091_intl_i386_zip.exe\"\n    }\n    \"6.0-AMD64\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/464090_intl_x64_zip.exe\"\n    }\n    \"6.1-x86\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/463983_intl_i386_zip.exe\"\n    }\n    \"6.1-AMD64\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/463984_intl_x64_zip.exe\"\n    }\n    \"6.2-x86\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/463940_intl_i386_zip.exe\"\n    }\n    \"6.2-AMD64\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/463941_intl_x64_zip.exe\"\n    }\n}\n\n$filename = $url.Split(\"/\")[-1]\n$compressed_file = \"$tmp_dir\\$($filename).zip\"\nDownload-File -url $url -path $compressed_file\nExtract-Zip -zip $compressed_file -dest $tmp_dir\n$file = Get-Item -Path \"$tmp_dir\\*$kb*.msu\"\nif ($file -eq $null) {\n    Write-Error -Message \"unable to find extracted msu file for hotfix KB\"\n    exit 1\n}\n\n$exit_code = Run-Process -executable $file.FullName -arguments \"/quiet /norestart\"\nif ($exit_code -eq 3010) {\n    Write-Verbose \"need to restart computer after hotfix $kb install\"\n    Restart-Computer -Confirm\n} elseif ($exit_code -ne 0) {\n    Write-Error -Message \"failed to install hotfix $($kb): exit code $exit_code\"\n} else {\n    Write-Verbose -Message \"hotfix $kb install complete\"\n}\nexit $exit_code\n"
  },
  {
    "path": "packer/proxmox/scripts/disable-screensaver.ps1",
    "content": "Write-Output \"Disabling Screensaver\"\nSet-ItemProperty \"HKCU:\\Control Panel\\Desktop\" -Name ScreenSaveActive -Value 0 -Type DWord\n& powercfg -x -monitor-timeout-ac 0\n& powercfg -x -monitor-timeout-dc 0\n"
  },
  {
    "path": "packer/proxmox/scripts/disable-winrm.ps1",
    "content": "netsh advfirewall firewall set rule name=\"Windows Remote Management (HTTP-In)\" new enable=yes action=block\nnetsh advfirewall firewall set rule group=\"Windows Remote Management\" new enable=yes\n$winrmService = Get-Service -Name WinRM\nif ($winrmService.Status -eq \"Running\") {\n  Disable-PSRemoting -Force\n}\nStop-Service winrm\nSet-Service -Name winrm -StartupType Disabled\n"
  },
  {
    "path": "packer/proxmox/scripts/enable-winrm.ps1",
    "content": "$NetworkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]\"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}\"))\n$Connections = $NetworkListManager.GetNetworkConnections()\n$Connections | ForEach-Object { $_.GetNetwork().SetCategory(1) }\n\nEnable-PSRemoting -Force\nwinrm quickconfig -q\nwinrm quickconfig -transport:http\nwinrm set winrm/config '@{MaxTimeoutms=\"1800000\"}'\nwinrm set winrm/config/winrs '@{MaxMemoryPerShellMB=\"800\"}'\nwinrm set winrm/config/service '@{AllowUnencrypted=\"true\"}'\nwinrm set winrm/config/service/auth '@{Basic=\"true\"}'\nwinrm set winrm/config/client/auth '@{Basic=\"true\"}'\n# winrm set winrm/config/listener?Address=*+Transport=HTTP '@{Port=\"5985\"}'\n# winrm set winrm/config/listener?Address=*+Transport=HTTPS '@{Port=\"5986\"}'\nnetsh advfirewall firewall set rule group=\"Windows Remote Administration\" new enable=yes\nnetsh advfirewall firewall set rule name=\"Windows Remote Management (HTTP-In)\" new enable=yes action=allow\nnetsh advfirewall firewall set rule name=\"Windows Remote Management (HTTPS-In)\" new enable=yes action=allow\nSet-WSManInstance -ResourceURI WinRM/Config/Client -ValueSet @{TrustedHosts=\"*\"}\nSet-Service winrm -startuptype \"auto\"\nRestart-Service winrm\n"
  },
  {
    "path": "packer/proxmox/scripts/fixnetwork.ps1",
    "content": "﻿# You cannot enable Windows PowerShell Remoting on network connections that are set to Public\n# Spin through all the network locations and if they are set to Public, set them to Private\n# using the INetwork interface:\n# http://msdn.microsoft.com/en-us/library/windows/desktop/aa370750(v=vs.85).aspx\n# For more info, see:\n# http://blogs.msdn.com/b/powershell/archive/2009/04/03/setting-network-location-to-private.aspx\n\nfunction Set-NetworkTypeToPrivate {\n  [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPositionalParameters', '')]\n  param()\n  # Network location feature was only introduced in Windows Vista - no need to bother with this\n  # if the operating system is older than Vista\n  if ([environment]::OSVersion.version.Major -lt 6) { return }\n\n  # You cannot change the network location if you are joined to a domain, so abort\n  if (1, 3, 4, 5 -contains (Get-CimInstance win32_computersystem).DomainRole) { return }\n\n  # Get network connections\n  $networkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]\"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}\"))\n  $connections = $networkListManager.GetNetworkConnections()\n\n  $connections | ForEach-Object {\n    Write-Output $_.GetNetwork().GetName() \"category was previously set to\" $_.GetNetwork().GetCategory()\n    #$_.GetNetwork().SetCategory(1)\n    Write-Output $_.GetNetwork().GetName() \"changed to category\" $_.GetNetwork().GetCategory()\n  }\n\n}\n\nSet-NetworkTypeToPrivate\n"
  },
  {
    "path": "packer/proxmox/scripts/microsoft-updates.bat",
    "content": "net stop wuauserv\n\nreg add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\" /v EnableFeaturedSoftware /t REG_DWORD /d 1 /f\n\nreg add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\" /v IncludeRecommendedUpdates /t REG_DWORD /d 1 /f\n\necho Set ServiceManager = CreateObject(\"Microsoft.Update.ServiceManager\") > A:\\temp.vbs\necho Set NewUpdateService = ServiceManager.AddService2(\"7971f918-a847-4430-9279-4a52d1efe18d\",7,\"\") >> A:\\temp.vbs\n\ncscript A:\\temp.vbs\n\nnet start wuauserv\n"
  },
  {
    "path": "packer/proxmox/scripts/set-proxy.ps1",
    "content": "$reg = \"HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\"\nSet-ItemProperty -Path $reg -Name ProxyServer -Value \"x.x.x.x:8080\"\nSet-ItemProperty -Path $reg -Name ProxyEnable -Value 1\n"
  },
  {
    "path": "packer/proxmox/scripts/sysprep/cloudbase-init-p2.ps1",
    "content": "while (!(Select-String -Path 'C:\\setup\\cloud-init.log' -Pattern 'Installation completed successfully' -Quiet)) {\n    echo \"Wait cloud-init installation end...\"\n    Start-Sleep 5\n}\n\necho \"Show cloudinit service\"\nGet-Service -Name cloudbase-init\n\necho \"Move config files to location\"\n# Move conf files to Cloudbase directory\ncopy-item \"G:\\sysprep\\cloudbase-init.conf\" \"C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\conf\\cloudbase-init.conf\" -force\ncopy-item \"G:\\sysprep\\cloudbase-init-unattend.conf\" \"C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\conf\\cloudbase-init-unattend.conf\" -force\ncopy-item \"G:\\sysprep\\cloudbase-init-unattend.xml\" \"C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\conf\\cloudbase-init-unattend.xml\" -force\n\necho \"Disable cloudbaseinit at start\"\n# disable cloudbase-init start\nSet-Service -Name cloudbase-init -StartupType Disabled\n\n# Run sysprep\ncd \"C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\conf\\\"\nstart-process -FilePath \"C:/Windows/system32/sysprep/sysprep.exe\" -ArgumentList \"/generalize /oobe /mode:vm /unattend:cloudbase-init-unattend.xml\" -wait\n"
  },
  {
    "path": "packer/proxmox/scripts/sysprep/cloudbase-init-unattend.conf",
    "content": "[DEFAULT]\nusername=Administrator\ngroups=Administrators\ninject_user_password=true\nconfig_drive_raw_hhd=true\nconfig_drive_cdrom=true\nconfig_drive_vfat=true\nbsdtar_path=C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\bin\\bsdtar.exe\nmtools_path=C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\bin\\\nverbose=true\ndebug=true\nlogdir=C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\log\\\nlogfile=cloudbase-init-unattend.log\ndefault_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN\nlogging_serial_port_settings=\nmtu_use_dhcp_config=true\nntp_use_dhcp_config=true\nlocal_scripts_path=C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\LocalScripts\\\nmetadata_services=cloudbaseinit.metadata.services.configdrive.ConfigDriveService\nplugins=cloudbaseinit.plugins.common.mtu.MTUPlugin,\n        cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin,\n        cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin,\n        cloudbaseinit.plugins.common.networkconfig.NetworkConfigPlugin,\n        cloudbaseinit.plugins.common.userdata.UserDataPlugin\nallow_reboot=false\nstop_service_on_exit=false\ncheck_latest_version=false"
  },
  {
    "path": "packer/proxmox/scripts/sysprep/cloudbase-init-unattend.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\r\n  <settings pass=\"generalize\">\r\n    <component name=\"Microsoft-Windows-Security-SPP\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n        <SkipRearm>0</SkipRearm>\r\n    </component>\r\n  </settings>\r\n  <settings pass=\"oobeSystem\">\r\n    <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\">\r\n      <OOBE>\r\n            <HideEULAPage>true</HideEULAPage>\r\n            <ProtectYourPC>3</ProtectYourPC>\r\n            <NetworkLocation>Work</NetworkLocation>\r\n            <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\r\n            <SkipUserOOBE>true</SkipUserOOBE>\r\n            <SkipMachineOOBE>true</SkipMachineOOBE>\r\n      </OOBE>\r\n      <UserAccounts>\r\n            <AdministratorPassword>\r\n                <Value>vagrant</Value>\r\n                <PlainText>true</PlainText>\r\n            </AdministratorPassword>\r\n            <LocalAccounts>\r\n                <LocalAccount wcm:action=\"add\">\r\n                    <Password>\r\n                        <Value>vagrant</Value>\r\n                        <PlainText>true</PlainText>\r\n                    </Password>\r\n                    <Group>administrators</Group>\r\n                    <DisplayName>Vagrant</DisplayName>\r\n                    <Name>vagrant</Name>\r\n                    <Description>Vagrant User</Description>\r\n                </LocalAccount>\r\n            </LocalAccounts>\r\n        </UserAccounts>\r\n    </component>\r\n  </settings>\r\n  <settings pass=\"specialize\">\r\n    <component name=\"Microsoft-Windows-Deployment\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n      <RunSynchronous>\r\n        <RunSynchronousCommand wcm:action=\"add\">\r\n            <Order>1</Order>\r\n            <Path>sc config cloudbase-init start= auto</Path>\r\n            <Description>Re-enable auto start of cloudbase-init</Description>\r\n            <WillReboot>Never</WillReboot>\r\n        </RunSynchronousCommand>\r\n      </RunSynchronous>\r\n    </component>\r\n  </settings>\r\n</unattend>"
  },
  {
    "path": "packer/proxmox/scripts/sysprep/cloudbase-init.conf",
    "content": "[DEFAULT]\nusername=Administrator\ngroups=Administrators\ninject_user_password=true\nconfig_drive_raw_hhd=true\nconfig_drive_cdrom=true\nconfig_drive_vfat=true\nbsdtar_path=C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\bin\\bsdtar.exe\nmtools_path=C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\bin\\\nverbose=true\ndebug=true\nlogdir=C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\log\\\nlogfile=cloudbase-init.log\ndefault_log_levels=comtypes=INFO,suds=INFO,iso8601=WARN,requests=WARN\nlogging_serial_port_settings=\nmtu_use_dhcp_config=true\nntp_use_dhcp_config=true\nlocal_scripts_path=C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\LocalScripts\\\nmetadata_services=cloudbaseinit.metadata.services.configdrive.ConfigDriveService\nplugins=cloudbaseinit.plugins.common.networkconfig.NetworkConfigPlugin,\n        cloudbaseinit.plugins.common.setuserpassword.SetUserPasswordPlugin,\n        cloudbaseinit.plugins.common.userdata.UserDataPlugin,\n        cloudbaseinit.plugins.common.sethostname.SetHostNamePlugin,\n        cloudbaseinit.plugins.common.mtu.MTUPlugin,\n        cloudbaseinit.plugins.windows.extendvolumes.ExtendVolumesPlugin\ncheck_latest_version=false"
  },
  {
    "path": "packer/proxmox/scripts/sysprep/cloudbase-init.ps1",
    "content": "# install Cloudbase-Init\nmkdir \"c:\\setup\"\necho \"Copy CloudbaseInitSetup_Stable_x64.msi\"\ncopy-item \"G:\\sysprep\\CloudbaseInitSetup_Stable_x64.msi\" \"c:\\setup\\CloudbaseInitSetup_Stable_x64.msi\" -force\n\necho \"Start process CloudbaseInitSetup_Stable_x64.msi\"\nstart-process -FilePath 'c:\\setup\\CloudbaseInitSetup_Stable_x64.msi' -ArgumentList '/qn /l*v C:\\setup\\cloud-init.log' -Wait\n"
  },
  {
    "path": "packer/proxmox/scripts/sysprep/sysprep.bat",
    "content": "echo \"Start Sysprep\"\ncd \"C:\\Program Files\\Cloudbase Solutions\\Cloudbase-Init\\conf\\\"\nc:\\windows\\system32\\sysprep\\sysprep.exe /generalize /oobe /unattend:cloudbase-init-unattend.xml /quit /shutdown"
  },
  {
    "path": "packer/proxmox/scripts/win-updates.ps1",
    "content": "[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '')]\r\nparam($global:RestartRequired = 0,\r\n  $global:MoreUpdates = 0,\r\n  $global:MaxCycles = 5,\r\n  $MaxUpdatesPerCycle = 500,\r\n  $BeginWithRestart = 0)\r\n\r\n$Logfile = \"C:\\Windows\\Temp\\win-updates.log\"\r\n\r\nfunction LogWrite {\r\n  Param ([string]$logstring)\r\n  $now = Get-Date -format s\r\n  Add-Content $Logfile -value \"$now $logstring\"\r\n  Write-Output $logstring\r\n}\r\n\r\nfunction Check-ContinueRestartOrEnd() {\r\n  $RegistryKey = \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\"\r\n  $RegistryEntry = \"InstallWindowsUpdates\"\r\n  switch ($global:RestartRequired) {\r\n    0 {\r\n      $prop = (Get-ItemProperty $RegistryKey).$RegistryEntry\r\n      if ($prop) {\r\n        LogWrite \"Restart Registry Entry Exists - Removing It\"\r\n        Remove-ItemProperty -Path $RegistryKey -Name $RegistryEntry -ErrorAction SilentlyContinue\r\n      }\r\n\r\n      LogWrite \"No Restart Required\"\r\n      Check-WindowsUpdates\r\n\r\n      if (($global:MoreUpdates -eq 1) -and ($script:Cycles -le $global:MaxCycles)) {\r\n        Install-WindowsUpdates\r\n      }\r\n      elseif ($script:Cycles -gt $global:MaxCycles) {\r\n        LogWrite \"Exceeded Cycle Count - Stopping\"\r\n        & \"G:\\ConfigureRemotingForAnsible.ps1\"\r\n      }\r\n      else {\r\n        LogWrite \"Done Installing Windows Updates\"\r\n        & \"G:\\ConfigureRemotingForAnsible.ps1\"\r\n      }\r\n    }\r\n    1 {\r\n      $prop = (Get-ItemProperty $RegistryKey).$RegistryEntry\r\n      if (-not $prop) {\r\n        LogWrite \"Restart Registry Entry Does Not Exist - Creating It\"\r\n        Set-ItemProperty -Path $RegistryKey -Name $RegistryEntry -Value \"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File $($script:ScriptPath) -MaxUpdatesPerCycle $($MaxUpdatesPerCycle)\"\r\n      }\r\n      else {\r\n        LogWrite \"Restart Registry Entry Exists Already\"\r\n      }\r\n\r\n      LogWrite \"Restart Required - Restarting...\"\r\n      Restart-Computer\r\n    }\r\n    default {\r\n      LogWrite \"Unsure If A Restart Is Required\"\r\n      break\r\n    }\r\n  }\r\n}\r\n\r\nfunction Install-WindowsUpdates()\r\n {\r\n  [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]\r\n  [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')]\r\n  param()\r\n  $script:Cycles++\r\n  LogWrite \"Evaluating Available Updates with limit of $($MaxUpdatesPerCycle):\"\r\n  $UpdatesToDownload = New-Object -ComObject 'Microsoft.Update.UpdateColl'\r\n  $script:i = 0;\r\n  $CurrentUpdates = $SearchResult.Updates\r\n  while ($script:i -lt $CurrentUpdates.Count -and $script:CycleUpdateCount -lt $MaxUpdatesPerCycle) {\r\n    $Update = $CurrentUpdates.Item($script:i)\r\n    if ($null -ne $Update) {\r\n      [bool]$addThisUpdate = $false\r\n      if ($Update.InstallationBehavior.CanRequestUserInput) {\r\n        LogWrite \"> Skipping: $($Update.Title) because it requires user input\"\r\n      }\r\n      else {\r\n        if (!($Update.EulaAccepted)) {\r\n          LogWrite \"> Note: $($Update.Title) has a license agreement that must be accepted. Accepting the license.\"\r\n          $Update.AcceptEula()\r\n          [bool]$addThisUpdate = $true\r\n          $script:CycleUpdateCount++\r\n        }\r\n        else {\r\n          [bool]$addThisUpdate = $true\r\n          $script:CycleUpdateCount++\r\n        }\r\n      }\r\n\r\n      if ([bool]$addThisUpdate) {\r\n        LogWrite \"Adding: $($Update.Title)\"\r\n        $UpdatesToDownload.Add($Update) | Out-Null\r\n      }\r\n    }\r\n    $script:i++\r\n  }\r\n\r\n  if ($UpdatesToDownload.Count -eq 0) {\r\n    LogWrite \"No Updates To Download...\"\r\n  }\r\n  else {\r\n    LogWrite 'Downloading Updates...'\r\n    $ok = 0;\r\n    while (! $ok) {\r\n      try {\r\n        $Downloader = $UpdateSession.CreateUpdateDownloader()\r\n        $Downloader.Updates = $UpdatesToDownload\r\n        $Downloader.Download()\r\n        $ok = 1;\r\n      }\r\n      catch {\r\n        LogWrite $_.Exception | Format-List -force\r\n        LogWrite \"Error downloading updates. Retrying in 30s.\"\r\n        $script:attempts = $script:attempts + 1\r\n        Start-Sleep -s 30\r\n      }\r\n    }\r\n  }\r\n\r\n  $UpdatesToInstall = New-Object -ComObject 'Microsoft.Update.UpdateColl'\r\n  [bool]$rebootMayBeRequired = $false\r\n  LogWrite 'The following updates are downloaded and ready to be installed:'\r\n  foreach ($Update in $SearchResult.Updates) {\r\n    if (($Update.IsDownloaded)) {\r\n      LogWrite \"> $($Update.Title)\"\r\n      $UpdatesToInstall.Add($Update) | Out-Null\r\n\r\n      if ($Update.InstallationBehavior.RebootBehavior -gt 0) {\r\n        [bool]$rebootMayBeRequired = $true\r\n      }\r\n    }\r\n  }\r\n\r\n  if ($UpdatesToInstall.Count -eq 0) {\r\n    LogWrite 'No updates available to install...'\r\n    $global:MoreUpdates = 0\r\n    $global:RestartRequired = 0\r\n    & \"G:\\ConfigureRemotingForAnsible.ps1\"\r\n    break\r\n  }\r\n\r\n  if ($rebootMayBeRequired) {\r\n    LogWrite 'These updates may require a reboot'\r\n    $global:RestartRequired = 1\r\n  }\r\n\r\n  LogWrite 'Installing updates...'\r\n\r\n  $Installer = $script:UpdateSession.CreateUpdateInstaller()\r\n  $Installer.Updates = $UpdatesToInstall\r\n  $InstallationResult = $Installer.Install()\r\n\r\n  LogWrite \"Installation Result: $($InstallationResult.ResultCode)\"\r\n  LogWrite \"Reboot Required: $($InstallationResult.RebootRequired)\"\r\n  LogWrite 'Listing of updates installed and individual installation results:'\r\n  if ($InstallationResult.RebootRequired) {\r\n    $global:RestartRequired = 1\r\n  }\r\n  else {\r\n    $global:RestartRequired = 0\r\n  }\r\n\r\n  for ($i = 0; $i -lt $UpdatesToInstall.Count; $i++) {\r\n    New-Object -TypeName PSObject -Property @{\r\n      Title  = $UpdatesToInstall.Item($i).Title\r\n      Result = $InstallationResult.GetUpdateResult($i).ResultCode\r\n    }\r\n    LogWrite \"Item: $($UpdatesToInstall.Item($i).Title)\"\r\n    LogWrite \"Result: $($InstallationResult.GetUpdateResult($i).ResultCode)\"\r\n  }\r\n\r\n  Check-ContinueRestartOrEnd\r\n}\r\n\r\nfunction Check-WindowsUpdates() {\r\n  [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]\r\n  [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')]\r\n  param()\r\n  LogWrite \"Checking For Windows Updates\"\r\n  $Username = $env:USERDOMAIN + \"\\\" + $env:USERNAME\r\n  LogWrite \"Script: $script:ScriptPath `nScript User: $Username `nStarted: $(Get-Date)\"\r\n\r\n  $script:UpdateSearcher = $script:UpdateSession.CreateUpdateSearcher()\r\n  $script:successful = $FALSE\r\n  $script:attempts = 0\r\n  $script:maxAttempts = 12\r\n  while (-not $script:successful -and $script:attempts -lt $script:maxAttempts) {\r\n    try {\r\n      $script:SearchResult = $script:UpdateSearcher.Search(\"IsInstalled=0 and Type='Software' and IsHidden=0\")\r\n      $script:successful = $TRUE\r\n    }\r\n    catch {\r\n      LogWrite $_.Exception | Format-List -force\r\n      LogWrite \"Search call to UpdateSearcher was unsuccessful. Retrying in 10s.\"\r\n      $script:attempts = $script:attempts + 1\r\n      Start-Sleep -s 10\r\n    }\r\n  }\r\n\r\n  if ($SearchResult.Updates.Count -ne 0) {\r\n    $Message = \"There are \" + $SearchResult.Updates.Count + \" more updates.\"\r\n    LogWrite $Message\r\n    try {\r\n      for ($i = 0; $i -lt $script:SearchResult.Updates.Count; $i++) {\r\n        LogWrite $script:SearchResult.Updates.Item($i).Title\r\n        LogWrite $script:SearchResult.Updates.Item($i).Description\r\n        LogWrite $script:SearchResult.Updates.Item($i).RebootRequired\r\n        LogWrite $script:SearchResult.Updates.Item($i).EulaAccepted\r\n      }\r\n      $global:MoreUpdates = 1\r\n    }\r\n    catch {\r\n      LogWrite $_.Exception | Format-List -force\r\n      LogWrite \"Showing SearchResult was unsuccessful. Rebooting.\"\r\n      $global:RestartRequired = 1\r\n      $global:MoreUpdates = 0\r\n      Check-ContinueRestartOrEnd\r\n      LogWrite \"Show never happen to see this text!\"\r\n      Restart-Computer\r\n    }\r\n  }\r\n  else {\r\n    LogWrite 'There are no applicable updates'\r\n    $global:RestartRequired = 0\r\n    $global:MoreUpdates = 0\r\n  }\r\n}\r\n\r\n$script:ScriptName = $MyInvocation.MyCommand.ToString()\r\n$script:ScriptPath = $MyInvocation.MyCommand.Path\r\n$script:UpdateSession = New-Object -ComObject 'Microsoft.Update.Session'\r\n$script:UpdateSession.ClientApplicationID = 'Packer Windows Update Installer'\r\n$script:UpdateSearcher = $script:UpdateSession.CreateUpdateSearcher()\r\n$script:SearchResult = New-Object -ComObject 'Microsoft.Update.UpdateColl'\r\n$script:Cycles = 0\r\n$script:CycleUpdateCount = 0\r\n\r\nif ($BeginWithRestart) {\r\n  $global:RestartRequired = 1\r\n  Check-ContinueRestartOrEnd\r\n}\r\n\r\nCheck-WindowsUpdates\r\nif ($global:MoreUpdates -eq 1) {\r\n  Install-WindowsUpdates\r\n}\r\nelse {\r\n  Check-ContinueRestartOrEnd\r\n}\r\n"
  },
  {
    "path": "packer/proxmox/variables.pkr.hcl",
    "content": "variable \"proxmox_url\" {}\nvariable \"proxmox_username\" {}\nvariable \"proxmox_password\" {}\nvariable \"proxmox_skip_tls_verify\" {}\nvariable \"proxmox_node\" {}\nvariable \"proxmox_pool\" {}\nvariable \"proxmox_vm_storage\" {}\nvariable \"proxmox_iso_storage\" {}\nvariable \"winrm_username\" {}\nvariable \"winrm_password\" {}\nvariable \"vm_name\" {}\nvariable \"template_description\" {}\nvariable \"iso_file\" {}\nvariable \"autounattend_iso\" {}\nvariable \"autounattend_checksum\" {}\nvariable \"vm_cpu_cores\" {}\nvariable \"vm_memory\" {}\nvariable \"vm_disk_size\" {}\nvariable \"vm_disk_format\" {}\nvariable \"vm_sockets\" {}\nvariable \"os\" {}\n"
  },
  {
    "path": "packer/proxmox/windows_10_22h2_proxmox_cloudinit.pkvars.hcl",
    "content": "winrm_username        = \"vagrant\"\nwinrm_password        = \"vagrant\"\nvm_name               = \"Windows10x64-22h2-cloudinit-qcow2\"\ntemplate_description  = \"Windows 10 - 22h2 - 64-bit - template built with Packer - {{isotime \\\"2006-01-02 03:04:05\\\"}}\"\niso_file              = \"local:iso/Windows-10-22h2_x64_en-us.iso\"\nautounattend_iso      = \"./iso/Autounattend_windows10_cloudinit.iso\"\nautounattend_checksum = \"sha256:bb5a28744077fd0121a04d5955f0b2f7a25d8aa13a1548a7223a4c2e2f1aed61\"\nvm_cpu_cores          = \"2\"\nvm_memory             = \"4096\"\nvm_disk_size          = \"60G\"\nvm_sockets            = \"1\"\nos                    = \"win10\"\nvm_disk_format        = \"qcow2\""
  },
  {
    "path": "packer/proxmox/windows_10_22h2_proxmox_cloudinit_uptodate.pkvars.hcl",
    "content": "winrm_username        = \"vagrant\"\nwinrm_password        = \"vagrant\"\nvm_name               = \"Windows10x64-22h2-cloudinit-qcow2-uptodate\"\ntemplate_description  = \"Windows 10 - 22h2 - 64-bit - template built with Packer - {{isotime \\\"2006-01-02 03:04:05\\\"}}\"\niso_file              = \"local:iso/Windows-10-22h2_x64_en-us.iso\"\nautounattend_iso      = \"./iso/Autounattend_windows10_cloudinit_uptodate.iso\"\nautounattend_checksum = \"sha256:bb5a28744077fd0121a04d5955f0b2f7a25d8aa13a1548a7223a4c2e2f1aed61\"\nvm_cpu_cores          = \"2\"\nvm_memory             = \"4096\"\nvm_disk_size          = \"80G\"\nvm_sockets            = \"1\"\nos                    = \"win10\"\nvm_disk_format        = \"qcow2\""
  },
  {
    "path": "packer/proxmox/windows_server2016_proxmox_cloudinit.pkvars.hcl",
    "content": "winrm_username = \"vagrant\"\nwinrm_password = \"vagrant\"\nvm_name = \"WinServer2016x64-cloudinit-qcow2\"\ntemplate_description = \"Windows Server 2016 64-bit - build 14393 - template built with Packer - cloudinit - {{isotime \\\"2006-01-02 03:04:05\\\"}}\"\niso_file = \"local:iso/windows_server_2016_14393.0_eval_x64.iso\"\nautounattend_iso = \"./iso/Autounattend_winserver2016_cloudinit.iso\"\nautounattend_checksum = \"sha256:541abf3910291616d26c1f4ede4478df022282987ab0e7aebcd12f17365dfe0e\"\nvm_cpu_cores = \"2\"\nvm_memory = \"4096\"\nvm_disk_size = \"40G\"\nvm_sockets = \"1\"\nos = \"win10\"\nvm_disk_format = \"qcow2\""
  },
  {
    "path": "packer/proxmox/windows_server2019_proxmox_cloudinit.pkvars.hcl",
    "content": "winrm_username        = \"vagrant\"\nwinrm_password        = \"vagrant\"\nvm_name               = \"WinServer2019x64-cloudinit-qcow2\"\ntemplate_description  = \"Windows Server 2019 64-bit - build 17763.737.190906-2324 - template built with Packer - cloudinit - {{isotime \\\"2006-01-02 03:04:05\\\"}}\"\niso_file              = \"local:iso/windows_server2019_x64FREE_en-us.iso\"\nautounattend_iso      = \"./iso/Autounattend_winserver2019_cloudinit.iso\"\nautounattend_checksum = \"sha256:2b3eeb1346c38a3ef5e4daefcf58d212471db7c8a95dd3dff831b78aaa246e8e\"\nvm_cpu_cores          = \"2\"\nvm_memory             = \"4096\"\nvm_disk_size          = \"40G\"\nvm_sockets            = \"1\"\nos                    = \"win10\"\nvm_disk_format        = \"qcow2\""
  },
  {
    "path": "packer/proxmox/windows_server2019_proxmox_cloudinit_uptodate.pkvars.hcl",
    "content": "winrm_username        = \"vagrant\"\nwinrm_password        = \"vagrant\"\nvm_name               = \"WinServer2019x64-cloudinit-qcow2-uptodate\"\ntemplate_description  = \"Windows Server 2019 64-bit - build 17763.737.190906-2324 - template built with Packer - cloudinit - {{isotime \\\"2006-01-02 03:04:05\\\"}}\"\niso_file              = \"local:iso/windows_server2019_x64FREE_en-us.iso\"\nautounattend_iso      = \"./iso/Autounattend_winserver2019_cloudinit_uptodate.iso\"\nautounattend_checksum = \"sha256:2b3eeb1346c38a3ef5e4daefcf58d212471db7c8a95dd3dff831b78aaa246e8e\"\nvm_cpu_cores          = \"2\"\nvm_memory             = \"4096\"\nvm_disk_size          = \"80G\"\nvm_sockets            = \"1\"\nos                    = \"win10\"\nvm_disk_format        = \"qcow2\""
  },
  {
    "path": "packer/vagrant/README.md",
    "content": "# packer for vbox and vmware\n\n- Adapted Recipes from https://github.com/StefanScherer/ repository\n- Used to build boxes : https://app.vagrantup.com/mayfly"
  },
  {
    "path": "packer/vagrant/answer_files/10/Autounattend.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\n    <servicing/>\n    <settings pass=\"windowsPE\">\n        <component name=\"Microsoft-Windows-PnpCustomizationsWinPE\"\n            publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\"\n            versionScope=\"nonSxS\" processorArchitecture=\"amd64\"\n            xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\">\n\n            <!--\n                 This makes the VirtIO drivers available to Windows, assuming that\n                 the VirtIO driver disk at https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso\n                 (see https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html#virtio-win-direct-downloads)\n                 is available as drive E:\n            -->\n            <DriverPaths>\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"2\">\n                    <Path>E:\\viostor\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"3\">\n                    <Path>E:\\NetKVM\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"4\">\n                    <Path>E:\\Balloon\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"5\">\n                    <Path>E:\\pvpanic\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"6\">\n                    <Path>E:\\qemupciserial\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"7\">\n                    <Path>E:\\qxldod\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"8\">\n                    <Path>E:\\vioinput\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"9\">\n                    <Path>E:\\viorng\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"10\">\n                    <Path>E:\\vioscsi\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"11\">\n                    <Path>E:\\vioserial\\w10\\amd64</Path>\n                </PathAndCredentials>\n            </DriverPaths>\n        </component>\n        \n        <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <DiskConfiguration>\n                <Disk wcm:action=\"add\">\n                    <CreatePartitions>\n                        <CreatePartition wcm:action=\"add\">\n                            <Order>1</Order>\n                            <Type>Primary</Type>\n                            <Extend>true</Extend>\n                        </CreatePartition>\n                    </CreatePartitions>\n                    <ModifyPartitions>\n                        <ModifyPartition wcm:action=\"add\">\n                            <Extend>false</Extend>\n                            <Format>NTFS</Format>\n                            <Letter>C</Letter>\n                            <Order>1</Order>\n                            <PartitionID>1</PartitionID>\n                            <Label>Windows 10</Label>\n                        </ModifyPartition>\n                    </ModifyPartitions>\n                    <DiskID>0</DiskID>\n                    <WillWipeDisk>true</WillWipeDisk>\n                </Disk>\n                <WillShowUI>OnError</WillShowUI>\n            </DiskConfiguration>\n            <UserData>\n                <AcceptEula>true</AcceptEula>\n                <FullName>Vagrant</FullName>\n                <Organization>Vagrant</Organization>\n\n                <!--\n                    NOTE: If you are re-configuring this for use of a retail key\n                    and using a retail ISO, you need to adjust the <ProductKey> block\n                    below to look like this:\n\n                    <ProductKey>\n                        <Key>W269N-WFGWX-YVC9B-4J6C9-T83GX</Key>\n                        <WillShowUI>Never</WillShowUI>\n                    </ProductKey>\n\n                    Notice the addition of the `<Key>` element.\n                -->\n\n                <!-- Product Key from https://www.microsoft.com/en-us/evalcenter/evaluate-windows-10-enterprise -->\n                <ProductKey>2FMYP-QCY43-QR9VK-WTVCK\n                    <WillShowUI>Never</WillShowUI>\n                </ProductKey>\n            </UserData>\n            <ImageInstall>\n                <OSImage>\n                    <InstallTo>\n                        <DiskID>0</DiskID>\n                        <PartitionID>1</PartitionID>\n                    </InstallTo>\n                    <WillShowUI>OnError</WillShowUI>\n                    <InstallToAvailablePartition>false</InstallToAvailablePartition>\n                    <InstallFrom>\n                        <MetaData wcm:action=\"add\">\n                            <Key>/IMAGE/NAME</Key>\n                            <Value>Windows 10 Enterprise Evaluation</Value>\n                        </MetaData>\n                    </InstallFrom>\n                </OSImage>\n            </ImageInstall>\n        </component>\n        <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-International-Core-WinPE\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <SetupUILanguage>\n                <UILanguage>en-US</UILanguage>\n            </SetupUILanguage>\n            <InputLocale>en-US</InputLocale>\n            <SystemLocale>en-US</SystemLocale>\n            <UILanguage>en-US</UILanguage>\n            <UILanguageFallback>en-US</UILanguageFallback>\n            <UserLocale>en-US</UserLocale>\n        </component>\n    </settings>\n    <settings pass=\"offlineServicing\">\n        <component name=\"Microsoft-Windows-LUA-Settings\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <EnableLUA>false</EnableLUA>\n        </component>\n    </settings>\n    <settings pass=\"oobeSystem\">\n        <component name=\"Microsoft-Windows-International-Core\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <InputLocale>en-US</InputLocale>\n            <SystemLocale>en-US</SystemLocale>\n            <UILanguage>en-US</UILanguage>\n            <UserLocale>en-US</UserLocale>\n        </component>\n        <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <UserAccounts>\n                <AdministratorPassword>\n                    <Value>vagrant</Value>\n                    <PlainText>true</PlainText>\n                </AdministratorPassword>\n                <LocalAccounts>\n                    <LocalAccount wcm:action=\"add\">\n                        <Password>\n                            <Value>vagrant</Value>\n                            <PlainText>true</PlainText>\n                        </Password>\n                        <Description>Vagrant User</Description>\n                        <DisplayName>vagrant</DisplayName>\n                        <Group>administrators</Group>\n                        <Name>vagrant</Name>\n                    </LocalAccount>\n                </LocalAccounts>\n            </UserAccounts>\n            <OOBE>\n                <HideEULAPage>true</HideEULAPage>\n                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\n                <NetworkLocation>Home</NetworkLocation>\n                <ProtectYourPC>1</ProtectYourPC>\n            </OOBE>\n            <AutoLogon>\n                <Password>\n                    <Value>vagrant</Value>\n                    <PlainText>true</PlainText>\n                </Password>\n                <Username>vagrant</Username>\n                <Enabled>true</Enabled>\n            </AutoLogon>\n            <FirstLogonCommands>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                    <Description>Set Execution Policy 64 Bit</Description>\n                    <Order>1</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>C:\\Windows\\SysWOW64\\cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                    <Description>Set Execution Policy 32 Bit</Description>\n                    <Order>2</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c reg add \"HKLM\\System\\CurrentControlSet\\Control\\Network\\NewNetworkWindowOff\"</CommandLine>\n                    <Description>Network prompt</Description>\n                    <Order>3</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\fixnetwork.ps1</CommandLine>\n                    <Description>Fix public network</Description>\n                    <Order>4</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-winrm.ps1</CommandLine>\n                    <Description>Disable WinRM</Description>\n                    <Order>5</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>6</Order>\n                    <Description>Show file extensions in Explorer</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>7</Order>\n                    <Description>Enable QuickEdit mode</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>8</Order>\n                    <Description>Show Run command in Start Menu</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>9</Order>\n                    <Description>Show Administrative Tools in Start Menu</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>10</Order>\n                    <Description>Zero Hibernation File</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>11</Order>\n                    <Description>Disable Hibernation Mode</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c wmic useraccount where \"name='vagrant'\" set PasswordExpires=FALSE</CommandLine>\n                    <Order>12</Order>\n                    <Description>Disable password expiration for vagrant user</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v DefaultPassword /t REG_SZ /d \"vagrant\" /f</CommandLine>\n                    <Order>13</Order>\n                    <Description>Enable AutoLogon</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v AutoAdminLogon /t REG_SZ /d 1 /f</CommandLine>\n                    <Order>14</Order>\n                    <Description>Enable AutoLogon</Description>\n                </SynchronousCommand>\n                <!-- WITHOUT WINDOWS UPDATES -->\n                <!--\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\enable-winrm.ps1</CommandLine>\n                    <Description>Enable WinRM</Description>\n                    <Order>99</Order>\n                </SynchronousCommand>\n                -->\n                <!-- END WITHOUT WINDOWS UPDATES -->\n                <!-- WITH WINDOWS UPDATES -->\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c a:\\microsoft-updates.bat</CommandLine>\n                    <Order>98</Order>\n                    <Description>Enable Microsoft Updates</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-screensaver.ps1</CommandLine>\n                    <Description>Disable Screensaver</Description>\n                    <Order>99</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\win-updates.ps1</CommandLine>\n                    <Description>Install Windows Updates</Description>\n                    <Order>100</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <!-- END WITH WINDOWS UPDATES -->\n            </FirstLogonCommands>\n            <ShowWindowsLive>false</ShowWindowsLive>\n        </component>\n    </settings>\n    <settings pass=\"specialize\">\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <OEMInformation>\n                <HelpCustomized>false</HelpCustomized>\n            </OEMInformation>\n            <!-- Rename computer here. -->\n            <ComputerName>vagrant-10</ComputerName>\n            <TimeZone>Pacific Standard Time</TimeZone>\n            <RegisteredOwner/>\n        </component>\n        <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Security-SPP-UX\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <SkipAutoActivation>true</SkipAutoActivation>\n        </component>\n    </settings>\n    <cpi:offlineImage xmlns:cpi=\"urn:schemas-microsoft-com:cpi\" cpi:source=\"catalog:d:/sources/install_windows 7 ENTERPRISE.clg\"/>\n</unattend>\n"
  },
  {
    "path": "packer/vagrant/answer_files/11/Autounattend.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\n    <servicing/>\n    <settings pass=\"windowsPE\">\n        <component name=\"Microsoft-Windows-PnpCustomizationsWinPE\"\n            publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\"\n            versionScope=\"nonSxS\" processorArchitecture=\"amd64\"\n            xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\">\n\n            <!--\n                 This makes the VirtIO drivers available to Windows, assuming that\n                 the VirtIO driver disk at https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso\n                 (see https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html#virtio-win-direct-downloads)\n                 is available as drive E:\n            -->\n            <DriverPaths>\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"2\">\n                    <Path>E:\\viostor\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"3\">\n                    <Path>E:\\NetKVM\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"4\">\n                    <Path>E:\\Balloon\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"5\">\n                    <Path>E:\\pvpanic\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"6\">\n                    <Path>E:\\qemupciserial\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"7\">\n                    <Path>E:\\qxldod\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"8\">\n                    <Path>E:\\vioinput\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"9\">\n                    <Path>E:\\viorng\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"10\">\n                    <Path>E:\\vioscsi\\w10\\amd64</Path>\n                </PathAndCredentials>\n\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"11\">\n                    <Path>E:\\vioserial\\w10\\amd64</Path>\n                </PathAndCredentials>\n            </DriverPaths>\n        </component>\n        \n        <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <DiskConfiguration>\n                <Disk wcm:action=\"add\">\n                    <CreatePartitions>\n                        <CreatePartition wcm:action=\"add\">\n                            <Order>1</Order>\n                            <Type>Primary</Type>\n                            <Extend>true</Extend>\n                        </CreatePartition>\n                    </CreatePartitions>\n                    <ModifyPartitions>\n                        <ModifyPartition wcm:action=\"add\">\n                            <Extend>false</Extend>\n                            <Format>NTFS</Format>\n                            <Letter>C</Letter>\n                            <Order>1</Order>\n                            <PartitionID>1</PartitionID>\n                            <Label>Windows 11</Label>\n                        </ModifyPartition>\n                    </ModifyPartitions>\n                    <DiskID>0</DiskID>\n                    <WillWipeDisk>true</WillWipeDisk>\n                </Disk>\n                <WillShowUI>OnError</WillShowUI>\n            </DiskConfiguration>\n            <UserData>\n                <AcceptEula>true</AcceptEula>\n                <FullName>Vagrant</FullName>\n                <Organization>Vagrant</Organization>\n\n                <!--\n                    NOTE: If you are re-configuring this for use of a retail key\n                    and using a retail ISO, you need to adjust the <ProductKey> block\n                    below to look like this:\n\n                    <ProductKey>\n                        <Key>W269N-WFGWX-YVC9B-4J6C9-T83GX</Key>\n                        <WillShowUI>Never</WillShowUI>\n                    </ProductKey>\n\n                    Notice the addition of the `<Key>` element.\n                -->\n            </UserData>\n            <ImageInstall>\n                <OSImage>\n                    <InstallTo>\n                        <DiskID>0</DiskID>\n                        <PartitionID>1</PartitionID>\n                    </InstallTo>\n                    <WillShowUI>OnError</WillShowUI>\n                    <InstallToAvailablePartition>false</InstallToAvailablePartition>\n                    <InstallFrom>\n                        <MetaData wcm:action=\"add\">\n                            <Key>/IMAGE/NAME</Key>\n                            <Value>Windows 11 Enterprise Evaluation</Value>\n                        </MetaData>\n                    </InstallFrom>\n                </OSImage>\n            </ImageInstall>\n        </component>\n        <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-International-Core-WinPE\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <SetupUILanguage>\n                <UILanguage>en-US</UILanguage>\n            </SetupUILanguage>\n            <InputLocale>en-US</InputLocale>\n            <SystemLocale>en-US</SystemLocale>\n            <UILanguage>en-US</UILanguage>\n            <UILanguageFallback>en-US</UILanguageFallback>\n            <UserLocale>en-US</UserLocale>\n        </component>\n    </settings>\n    <settings pass=\"offlineServicing\">\n        <component name=\"Microsoft-Windows-LUA-Settings\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <EnableLUA>false</EnableLUA>\n        </component>\n    </settings>\n    <settings pass=\"oobeSystem\">\n        <component name=\"Microsoft-Windows-International-Core\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n            <InputLocale>en-US</InputLocale>\n            <SystemLocale>en-US</SystemLocale>\n            <UILanguage>en-US</UILanguage>\n            <UserLocale>en-US</UserLocale>\n        </component>\n        <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <UserAccounts>\n                <AdministratorPassword>\n                    <Value>vagrant</Value>\n                    <PlainText>true</PlainText>\n                </AdministratorPassword>\n                <LocalAccounts>\n                    <LocalAccount wcm:action=\"add\">\n                        <Password>\n                            <Value>vagrant</Value>\n                            <PlainText>true</PlainText>\n                        </Password>\n                        <Description>Vagrant User</Description>\n                        <DisplayName>vagrant</DisplayName>\n                        <Group>administrators</Group>\n                        <Name>vagrant</Name>\n                    </LocalAccount>\n                </LocalAccounts>\n            </UserAccounts>\n            <OOBE>\n                <HideEULAPage>true</HideEULAPage>\n                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\n                <NetworkLocation>Home</NetworkLocation>\n                <ProtectYourPC>1</ProtectYourPC>\n            </OOBE>\n            <AutoLogon>\n                <Password>\n                    <Value>vagrant</Value>\n                    <PlainText>true</PlainText>\n                </Password>\n                <Username>vagrant</Username>\n                <Enabled>true</Enabled>\n            </AutoLogon>\n            <FirstLogonCommands>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                    <Description>Set Execution Policy 64 Bit</Description>\n                    <Order>1</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>C:\\Windows\\SysWOW64\\cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\n                    <Description>Set Execution Policy 32 Bit</Description>\n                    <Order>2</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c reg add \"HKLM\\System\\CurrentControlSet\\Control\\Network\\NewNetworkWindowOff\"</CommandLine>\n                    <Description>Network prompt</Description>\n                    <Order>3</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\fixnetwork.ps1</CommandLine>\n                    <Description>Fix public network</Description>\n                    <Order>4</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-winrm.ps1</CommandLine>\n                    <Description>Disable WinRM</Description>\n                    <Order>5</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>6</Order>\n                    <Description>Show file extensions in Explorer</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>7</Order>\n                    <Description>Enable QuickEdit mode</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>8</Order>\n                    <Description>Show Run command in Start Menu</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine>\n                    <Order>9</Order>\n                    <Description>Show Administrative Tools in Start Menu</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>10</Order>\n                    <Description>Zero Hibernation File</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine>\n                    <Order>11</Order>\n                    <Description>Disable Hibernation Mode</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c wmic useraccount where \"name='vagrant'\" set PasswordExpires=FALSE</CommandLine>\n                    <Order>12</Order>\n                    <Description>Disable password expiration for vagrant user</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v DefaultPassword /t REG_SZ /d \"vagrant\" /f</CommandLine>\n                    <Order>13</Order>\n                    <Description>Enable AutoLogon</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v AutoAdminLogon /t REG_SZ /d 1 /f</CommandLine>\n                    <Order>14</Order>\n                    <Description>Enable AutoLogon</Description>\n                </SynchronousCommand>\n                <!-- WITHOUT WINDOWS UPDATES -->\n                <!--\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\enable-winrm.ps1</CommandLine>\n                    <Description>Enable WinRM</Description>\n                    <Order>99</Order>\n                </SynchronousCommand>\n                -->\n                <!-- END WITHOUT WINDOWS UPDATES -->\n                <!-- WITH WINDOWS UPDATES -->\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c a:\\microsoft-updates.bat</CommandLine>\n                    <Order>98</Order>\n                    <Description>Enable Microsoft Updates</Description>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-screensaver.ps1</CommandLine>\n                    <Description>Disable Screensaver</Description>\n                    <Order>99</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <SynchronousCommand wcm:action=\"add\">\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\win-updates.ps1</CommandLine>\n                    <Description>Install Windows Updates</Description>\n                    <Order>100</Order>\n                    <RequiresUserInput>true</RequiresUserInput>\n                </SynchronousCommand>\n                <!-- END WITH WINDOWS UPDATES -->\n            </FirstLogonCommands>\n            <ShowWindowsLive>false</ShowWindowsLive>\n        </component>\n    </settings>\n    <settings pass=\"specialize\">\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <OEMInformation>\n                <HelpCustomized>false</HelpCustomized>\n            </OEMInformation>\n            <!-- Rename computer here. -->\n            <ComputerName>vagrant-11</ComputerName>\n            <TimeZone>Pacific Standard Time</TimeZone>\n            <RegisteredOwner/>\n        </component>\n        <component xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"Microsoft-Windows-Security-SPP-UX\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\">\n            <SkipAutoActivation>true</SkipAutoActivation>\n        </component>\n    </settings>\n    <cpi:offlineImage xmlns:cpi=\"urn:schemas-microsoft-com:cpi\" cpi:source=\"catalog:d:/sources/install_windows 7 ENTERPRISE.clg\"/>\n</unattend>\n"
  },
  {
    "path": "packer/vagrant/answer_files/2016/Autounattend.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\r\n    <settings pass=\"windowsPE\">\r\n        <component name=\"Microsoft-Windows-International-Core-WinPE\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <SetupUILanguage>\r\n                <UILanguage>en-US</UILanguage>\r\n            </SetupUILanguage>\r\n            <InputLocale>en-US</InputLocale>\r\n            <SystemLocale>en-US</SystemLocale>\r\n            <UILanguage>en-US</UILanguage>\r\n            <UILanguageFallback>en-US</UILanguageFallback>\r\n            <UserLocale>en-US</UserLocale>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <DiskConfiguration>\r\n                <Disk wcm:action=\"add\">\r\n                    <CreatePartitions>\r\n                        <CreatePartition wcm:action=\"add\">\r\n                            <Type>Primary</Type>\r\n                            <Order>1</Order>\r\n                            <Size>350</Size>\r\n                        </CreatePartition>\r\n                        <CreatePartition wcm:action=\"add\">\r\n                            <Order>2</Order>\r\n                            <Type>Primary</Type>\r\n                            <Extend>true</Extend>\r\n                        </CreatePartition>\r\n                    </CreatePartitions>\r\n                    <ModifyPartitions>\r\n                        <ModifyPartition wcm:action=\"add\">\r\n                            <Active>true</Active>\r\n                            <Format>NTFS</Format>\r\n                            <Label>boot</Label>\r\n                            <Order>1</Order>\r\n                            <PartitionID>1</PartitionID>\r\n                        </ModifyPartition>\r\n                        <ModifyPartition wcm:action=\"add\">\r\n                            <Format>NTFS</Format>\r\n                            <Label>Windows 2016</Label>\r\n                            <Letter>C</Letter>\r\n                            <Order>2</Order>\r\n                            <PartitionID>2</PartitionID>\r\n                        </ModifyPartition>\r\n                    </ModifyPartitions>\r\n                    <DiskID>0</DiskID>\r\n                    <WillWipeDisk>true</WillWipeDisk>\r\n                </Disk>\r\n            </DiskConfiguration>\r\n            <ImageInstall>\r\n                <OSImage>\r\n                    <InstallFrom>\r\n                        <MetaData wcm:action=\"add\">\r\n                            <Key>/IMAGE/NAME</Key>\r\n                            <Value>Windows Server 2016 SERVERSTANDARD</Value>\r\n                        </MetaData>\r\n                    </InstallFrom>\r\n                    <InstallTo>\r\n                        <DiskID>0</DiskID>\r\n                        <PartitionID>2</PartitionID>\r\n                    </InstallTo>\r\n                </OSImage>\r\n            </ImageInstall>\r\n            <UserData>\r\n                <!-- Product Key from https://www.microsoft.com/de-de/evalcenter/evaluate-windows-server-technical-preview?i=1 -->\r\n                <ProductKey>\r\n                    <!-- Do not uncomment the Key element if you are using trial ISOs -->\r\n                    <!-- You must uncomment the Key element (and optionally insert your own key) if you are using retail or volume license ISOs -->\r\n                    <!-- <Key>6XBNX-4JQGW-QX6QG-74P76-72V67</Key> -->\r\n                    <WillShowUI>OnError</WillShowUI>\r\n                </ProductKey>\r\n                <AcceptEula>true</AcceptEula>\r\n                <FullName>Vagrant</FullName>\r\n                <Organization>Vagrant</Organization>\r\n            </UserData>\r\n        </component>\r\n    </settings>\r\n    <settings pass=\"specialize\">\r\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <OEMInformation>\r\n                <HelpCustomized>false</HelpCustomized>\r\n            </OEMInformation>\r\n            <ComputerName>vagrant-2016</ComputerName>\r\n            <TimeZone>Pacific Standard Time</TimeZone>\r\n            <RegisteredOwner/>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-ServerManager-SvrMgrNc\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-IE-ESC\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <IEHardenAdmin>false</IEHardenAdmin>\r\n            <IEHardenUser>false</IEHardenUser>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-OutOfBoxExperience\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-Security-SPP-UX\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <SkipAutoActivation>true</SkipAutoActivation>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-Deployment\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <RunSynchronous>\r\n                <RunSynchronousCommand wcm:action=\"add\">\r\n                    <Order>1</Order>\r\n                    <Description>Set Execution Policy 64 Bit</Description>\r\n                    <Path>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</Path>\r\n                </RunSynchronousCommand>\r\n                <RunSynchronousCommand wcm:action=\"add\">\r\n                    <Order>2</Order>\r\n                    <Description>Set Execution Policy 32 Bit</Description>\r\n                    <Path>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</Path>\r\n                </RunSynchronousCommand>\r\n                <RunSynchronousCommand wcm:action=\"add\">\r\n                    <Order>3</Order>\r\n                    <Description>Disable WinRM</Description>\r\n                    <Path>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-winrm.ps1</Path>\r\n                </RunSynchronousCommand>\r\n            </RunSynchronous>\r\n        </component>\r\n    </settings>\r\n    <settings pass=\"oobeSystem\">\r\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <AutoLogon>\r\n                <Password>\r\n                    <Value>vagrant</Value>\r\n                    <PlainText>true</PlainText>\r\n                </Password>\r\n                <Enabled>true</Enabled>\r\n                <Username>vagrant</Username>\r\n            </AutoLogon>\r\n            <FirstLogonCommands>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\r\n                    <Description>Set Execution Policy 64 Bit</Description>\r\n                    <Order>1</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>C:\\Windows\\SysWOW64\\cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\r\n                    <Description>Set Execution Policy 32 Bit</Description>\r\n                    <Order>2</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-winrm.ps1</CommandLine>\r\n                    <Description>Disable WinRM</Description>\r\n                    <Order>3</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>\r\n                    <Order>4</Order>\r\n                    <Description>Show file extensions in Explorer</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine>\r\n                    <Order>5</Order>\r\n                    <Description>Enable QuickEdit mode</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine>\r\n                    <Order>6</Order>\r\n                    <Description>Show Run command in Start Menu</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine>\r\n                    <Order>7</Order>\r\n                    <Description>Show Administrative Tools in Start Menu</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine>\r\n                    <Order>8</Order>\r\n                    <Description>Zero Hibernation File</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine>\r\n                    <Order>9</Order>\r\n                    <Description>Disable Hibernation Mode</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c wmic useraccount where \"name='vagrant'\" set PasswordExpires=FALSE</CommandLine>\r\n                    <Order>10</Order>\r\n                    <Description>Disable password expiration for vagrant user</Description>\r\n                </SynchronousCommand>\r\n                <!-- WITHOUT WINDOWS UPDATES -->\r\n                <!--\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\enable-winrm.ps1</CommandLine>\r\n                    <Description>Enable WinRM</Description>\r\n                    <Order>99</Order>\r\n                </SynchronousCommand>\r\n                -->\r\n                <!-- END WITHOUT WINDOWS UPDATES -->\r\n                <!-- WITH WINDOWS UPDATES -->\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c a:\\microsoft-updates.bat</CommandLine>\r\n                    <Order>98</Order>\r\n                    <Description>Enable Microsoft Updates</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-screensaver.ps1</CommandLine>\r\n                    <Description>Disable Screensaver</Description>\r\n                    <Order>99</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\win-updates.ps1</CommandLine>\r\n                    <Description>Install Windows Updates</Description>\r\n                    <Order>100</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <!-- END WITH WINDOWS UPDATES -->\r\n            </FirstLogonCommands>\r\n            <OOBE>\r\n                <HideEULAPage>true</HideEULAPage>\r\n                <HideLocalAccountScreen>true</HideLocalAccountScreen>\r\n                <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>\r\n                <HideOnlineAccountScreens>true</HideOnlineAccountScreens>\r\n                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\r\n                <NetworkLocation>Home</NetworkLocation>\r\n                <ProtectYourPC>1</ProtectYourPC>\r\n            </OOBE>\r\n            <UserAccounts>\r\n                <AdministratorPassword>\r\n                    <Value>vagrant</Value>\r\n                    <PlainText>true</PlainText>\r\n                </AdministratorPassword>\r\n                <LocalAccounts>\r\n                    <LocalAccount wcm:action=\"add\">\r\n                        <Password>\r\n                            <Value>vagrant</Value>\r\n                            <PlainText>true</PlainText>\r\n                        </Password>\r\n                        <Group>administrators</Group>\r\n                        <DisplayName>Vagrant</DisplayName>\r\n                        <Name>vagrant</Name>\r\n                        <Description>Vagrant User</Description>\r\n                    </LocalAccount>\r\n                </LocalAccounts>\r\n            </UserAccounts>\r\n            <RegisteredOwner />\r\n        </component>\r\n    </settings>\r\n    <settings pass=\"offlineServicing\">\r\n        <component name=\"Microsoft-Windows-LUA-Settings\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <EnableLUA>false</EnableLUA>\r\n        </component>\r\n    </settings>\r\n    <cpi:offlineImage cpi:source=\"wim:c:/wim/install.wim#Windows Server 2012 R2 SERVERSTANDARD\" xmlns:cpi=\"urn:schemas-microsoft-com:cpi\" />\r\n</unattend>\r\n"
  },
  {
    "path": "packer/vagrant/answer_files/2019/Autounattend.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\r\n    <settings pass=\"windowsPE\">\r\n        <component name=\"Microsoft-Windows-PnpCustomizationsWinPE\"\r\n            publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\"\r\n            versionScope=\"nonSxS\" processorArchitecture=\"amd64\"\r\n            xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\">\r\n\r\n            <!--\r\n                 This makes the VirtIO drivers available to Windows, assuming that\r\n                 the VirtIO driver disk at https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso\r\n                 (see https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html#virtio-win-direct-downloads)\r\n                 is available as drive E:\r\n            -->\r\n            <DriverPaths>\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"2\">\r\n                    <Path>E:\\viostor\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"3\">\r\n                    <Path>E:\\NetKVM\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"4\">\r\n                    <Path>E:\\Balloon\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"5\">\r\n                    <Path>E:\\pvpanic\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"6\">\r\n                    <Path>E:\\qemupciserial\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"7\">\r\n                    <Path>E:\\qxldod\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"8\">\r\n                    <Path>E:\\vioinput\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"9\">\r\n                    <Path>E:\\viorng\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"10\">\r\n                    <Path>E:\\vioscsi\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"11\">\r\n                    <Path>E:\\vioserial\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n            </DriverPaths>\r\n        </component>\r\n\r\n        <component name=\"Microsoft-Windows-International-Core-WinPE\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <SetupUILanguage>\r\n                <UILanguage>en-US</UILanguage>\r\n            </SetupUILanguage>\r\n            <InputLocale>en-US</InputLocale>\r\n            <SystemLocale>en-US</SystemLocale>\r\n            <UILanguage>en-US</UILanguage>\r\n            <UILanguageFallback>en-US</UILanguageFallback>\r\n            <UserLocale>en-US</UserLocale>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <DiskConfiguration>\r\n                <Disk wcm:action=\"add\">\r\n                    <CreatePartitions>\r\n                        <CreatePartition wcm:action=\"add\">\r\n                            <Type>Primary</Type>\r\n                            <Order>1</Order>\r\n                            <Size>350</Size>\r\n                        </CreatePartition>\r\n                        <CreatePartition wcm:action=\"add\">\r\n                            <Order>2</Order>\r\n                            <Type>Primary</Type>\r\n                            <Extend>true</Extend>\r\n                        </CreatePartition>\r\n                    </CreatePartitions>\r\n                    <ModifyPartitions>\r\n                        <ModifyPartition wcm:action=\"add\">\r\n                            <Active>true</Active>\r\n                            <Format>NTFS</Format>\r\n                            <Label>boot</Label>\r\n                            <Order>1</Order>\r\n                            <PartitionID>1</PartitionID>\r\n                        </ModifyPartition>\r\n                        <ModifyPartition wcm:action=\"add\">\r\n                            <Format>NTFS</Format>\r\n                            <Label>Windows 2019</Label>\r\n                            <Letter>C</Letter>\r\n                            <Order>2</Order>\r\n                            <PartitionID>2</PartitionID>\r\n                        </ModifyPartition>\r\n                    </ModifyPartitions>\r\n                    <DiskID>0</DiskID>\r\n                    <WillWipeDisk>true</WillWipeDisk>\r\n                </Disk>\r\n            </DiskConfiguration>\r\n            <ImageInstall>\r\n                <OSImage>\r\n                    <InstallFrom>\r\n                        <MetaData wcm:action=\"add\">\r\n                            <Key>/IMAGE/NAME</Key>\r\n                            <Value>Windows Server 2019 SERVERDATACENTER</Value>\r\n                        </MetaData>\r\n                    </InstallFrom>\r\n                    <InstallTo>\r\n                        <DiskID>0</DiskID>\r\n                        <PartitionID>2</PartitionID>\r\n                    </InstallTo>\r\n                </OSImage>\r\n            </ImageInstall>\r\n            <UserData>\r\n                <!-- Product Key from https://www.microsoft.com/de-de/evalcenter/evaluate-windows-server-technical-preview?i=1 -->\r\n                <ProductKey>\r\n                    <!-- Do not uncomment the Key element if you are using trial ISOs -->\r\n                    <!-- You must uncomment the Key element (and optionally insert your own key) if you are using retail or volume license ISOs -->\r\n                    <!-- <Key>6XBNX-4JQGW-QX6QG-74P76-72V67</Key> -->\r\n                    <WillShowUI>OnError</WillShowUI>\r\n                </ProductKey>\r\n                <AcceptEula>true</AcceptEula>\r\n                <FullName>Vagrant</FullName>\r\n                <Organization>Vagrant</Organization>\r\n            </UserData>\r\n        </component>\r\n    </settings>\r\n    <settings pass=\"specialize\">\r\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <OEMInformation>\r\n                <HelpCustomized>false</HelpCustomized>\r\n            </OEMInformation>\r\n            <ComputerName>vagrant-2019</ComputerName>\r\n            <TimeZone>Pacific Standard Time</TimeZone>\r\n            <RegisteredOwner/>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-ServerManager-SvrMgrNc\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-IE-ESC\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <IEHardenAdmin>false</IEHardenAdmin>\r\n            <IEHardenUser>false</IEHardenUser>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-OutOfBoxExperience\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-Security-SPP-UX\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <SkipAutoActivation>true</SkipAutoActivation>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-Deployment\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <RunSynchronous>\r\n                <RunSynchronousCommand wcm:action=\"add\">\r\n                    <Order>1</Order>\r\n                    <Description>Set Execution Policy 64 Bit</Description>\r\n                    <Path>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</Path>\r\n                </RunSynchronousCommand>\r\n                <RunSynchronousCommand wcm:action=\"add\">\r\n                    <Order>2</Order>\r\n                    <Description>Set Execution Policy 32 Bit</Description>\r\n                    <Path>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</Path>\r\n                </RunSynchronousCommand>\r\n                <RunSynchronousCommand wcm:action=\"add\">\r\n                    <Order>3</Order>\r\n                    <Description>Disable WinRM</Description>\r\n                    <Path>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-winrm.ps1</Path>\r\n                </RunSynchronousCommand>\r\n            </RunSynchronous>\r\n        </component>\r\n    </settings>\r\n    <settings pass=\"oobeSystem\">\r\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <AutoLogon>\r\n                <Password>\r\n                    <Value>vagrant</Value>\r\n                    <PlainText>true</PlainText>\r\n                </Password>\r\n                <Enabled>true</Enabled>\r\n                <Username>vagrant</Username>\r\n            </AutoLogon>\r\n            <FirstLogonCommands>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\r\n                    <Description>Set Execution Policy 64 Bit</Description>\r\n                    <Order>1</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>C:\\Windows\\SysWOW64\\cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\r\n                    <Description>Set Execution Policy 32 Bit</Description>\r\n                    <Order>2</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-winrm.ps1</CommandLine>\r\n                    <Description>Disable WinRM</Description>\r\n                    <Order>3</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>\r\n                    <Order>4</Order>\r\n                    <Description>Show file extensions in Explorer</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine>\r\n                    <Order>5</Order>\r\n                    <Description>Enable QuickEdit mode</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine>\r\n                    <Order>6</Order>\r\n                    <Description>Show Run command in Start Menu</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine>\r\n                    <Order>7</Order>\r\n                    <Description>Show Administrative Tools in Start Menu</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine>\r\n                    <Order>8</Order>\r\n                    <Description>Zero Hibernation File</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine>\r\n                    <Order>9</Order>\r\n                    <Description>Disable Hibernation Mode</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c wmic useraccount where \"name='vagrant'\" set PasswordExpires=FALSE</CommandLine>\r\n                    <Order>10</Order>\r\n                    <Description>Disable password expiration for vagrant user</Description>\r\n                </SynchronousCommand>\r\n                <!-- WITHOUT WINDOWS UPDATES -->\r\n                <!--\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\enable-winrm.ps1</CommandLine>\r\n                    <Description>Enable WinRM</Description>\r\n                    <Order>99</Order>\r\n                </SynchronousCommand>\r\n                -->\r\n                <!-- END WITHOUT WINDOWS UPDATES -->\r\n                <!-- WITH WINDOWS UPDATES -->\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c a:\\microsoft-updates.bat</CommandLine>\r\n                    <Order>98</Order>\r\n                    <Description>Enable Microsoft Updates</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-screensaver.ps1</CommandLine>\r\n                    <Description>Disable Screensaver</Description>\r\n                    <Order>99</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\win-updates.ps1</CommandLine>\r\n                    <Description>Install Windows Updates</Description>\r\n                    <Order>100</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <!-- END WITH WINDOWS UPDATES -->\r\n            </FirstLogonCommands>\r\n            <OOBE>\r\n                <HideEULAPage>true</HideEULAPage>\r\n                <HideLocalAccountScreen>true</HideLocalAccountScreen>\r\n                <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>\r\n                <HideOnlineAccountScreens>true</HideOnlineAccountScreens>\r\n                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\r\n                <NetworkLocation>Home</NetworkLocation>\r\n                <ProtectYourPC>1</ProtectYourPC>\r\n            </OOBE>\r\n            <UserAccounts>\r\n                <AdministratorPassword>\r\n                    <Value>vagrant</Value>\r\n                    <PlainText>true</PlainText>\r\n                </AdministratorPassword>\r\n                <LocalAccounts>\r\n                    <LocalAccount wcm:action=\"add\">\r\n                        <Password>\r\n                            <Value>vagrant</Value>\r\n                            <PlainText>true</PlainText>\r\n                        </Password>\r\n                        <Group>administrators</Group>\r\n                        <DisplayName>Vagrant</DisplayName>\r\n                        <Name>vagrant</Name>\r\n                        <Description>Vagrant User</Description>\r\n                    </LocalAccount>\r\n                </LocalAccounts>\r\n            </UserAccounts>\r\n            <RegisteredOwner />\r\n        </component>\r\n    </settings>\r\n    <settings pass=\"offlineServicing\">\r\n        <component name=\"Microsoft-Windows-LUA-Settings\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <EnableLUA>false</EnableLUA>\r\n        </component>\r\n    </settings>\r\n    <cpi:offlineImage cpi:source=\"wim:c:/wim/install.wim#Windows Server 2012 R2 SERVERSTANDARD\" xmlns:cpi=\"urn:schemas-microsoft-com:cpi\" />\r\n</unattend>\r\n"
  },
  {
    "path": "packer/vagrant/answer_files/2022/Autounattend.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\r\n    <settings pass=\"windowsPE\">\r\n        <component name=\"Microsoft-Windows-PnpCustomizationsWinPE\"\r\n            publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\"\r\n            versionScope=\"nonSxS\" processorArchitecture=\"amd64\"\r\n            xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\">\r\n\r\n            <!--\r\n                 This makes the VirtIO drivers available to Windows, assuming that\r\n                 the VirtIO driver disk at https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso\r\n                 (see https://docs.fedoraproject.org/en-US/quick-docs/creating-windows-virtual-machines-using-virtio-drivers/index.html#virtio-win-direct-downloads)\r\n                 is available as drive E:\r\n            -->\r\n            <DriverPaths>\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"2\">\r\n                    <Path>E:\\viostor\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"3\">\r\n                    <Path>E:\\NetKVM\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"4\">\r\n                    <Path>E:\\Balloon\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"5\">\r\n                    <Path>E:\\pvpanic\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"6\">\r\n                    <Path>E:\\qemupciserial\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"7\">\r\n                    <Path>E:\\qxldod\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"8\">\r\n                    <Path>E:\\vioinput\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"9\">\r\n                    <Path>E:\\viorng\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"10\">\r\n                    <Path>E:\\vioscsi\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n\r\n                <PathAndCredentials wcm:action=\"add\" wcm:keyValue=\"11\">\r\n                    <Path>E:\\vioserial\\2k19\\amd64</Path>\r\n                </PathAndCredentials>\r\n            </DriverPaths>\r\n        </component>\r\n\r\n        <component name=\"Microsoft-Windows-International-Core-WinPE\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <SetupUILanguage>\r\n                <UILanguage>en-US</UILanguage>\r\n            </SetupUILanguage>\r\n            <InputLocale>en-US</InputLocale>\r\n            <SystemLocale>en-US</SystemLocale>\r\n            <UILanguage>en-US</UILanguage>\r\n            <UILanguageFallback>en-US</UILanguageFallback>\r\n            <UserLocale>en-US</UserLocale>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <DiskConfiguration>\r\n                <Disk wcm:action=\"add\">\r\n                    <CreatePartitions>\r\n                        <CreatePartition wcm:action=\"add\">\r\n                            <Type>Primary</Type>\r\n                            <Order>1</Order>\r\n                            <Size>350</Size>\r\n                        </CreatePartition>\r\n                        <CreatePartition wcm:action=\"add\">\r\n                            <Order>2</Order>\r\n                            <Type>Primary</Type>\r\n                            <Extend>true</Extend>\r\n                        </CreatePartition>\r\n                    </CreatePartitions>\r\n                    <ModifyPartitions>\r\n                        <ModifyPartition wcm:action=\"add\">\r\n                            <Active>true</Active>\r\n                            <Format>NTFS</Format>\r\n                            <Label>boot</Label>\r\n                            <Order>1</Order>\r\n                            <PartitionID>1</PartitionID>\r\n                        </ModifyPartition>\r\n                        <ModifyPartition wcm:action=\"add\">\r\n                            <Format>NTFS</Format>\r\n                            <Label>Windows 2022</Label>\r\n                            <Letter>C</Letter>\r\n                            <Order>2</Order>\r\n                            <PartitionID>2</PartitionID>\r\n                        </ModifyPartition>\r\n                    </ModifyPartitions>\r\n                    <DiskID>0</DiskID>\r\n                    <WillWipeDisk>true</WillWipeDisk>\r\n                </Disk>\r\n            </DiskConfiguration>\r\n            <ImageInstall>\r\n                <OSImage>\r\n                    <InstallFrom>\r\n                        <MetaData wcm:action=\"add\">\r\n                            <Key>/IMAGE/NAME</Key>\r\n                            <Value>Windows Server 2022 SERVERDATACENTER</Value>\r\n                        </MetaData>\r\n                    </InstallFrom>\r\n                    <InstallTo>\r\n                        <DiskID>0</DiskID>\r\n                        <PartitionID>2</PartitionID>\r\n                    </InstallTo>\r\n                </OSImage>\r\n            </ImageInstall>\r\n            <UserData>\r\n                <!-- Product Key from https://www.microsoft.com/de-de/evalcenter/evaluate-windows-server-technical-preview?i=1 -->\r\n                <ProductKey>\r\n                    <!-- Do not uncomment the Key element if you are using trial ISOs -->\r\n                    <!-- You must uncomment the Key element (and optionally insert your own key) if you are using retail or volume license ISOs -->\r\n                    <!-- <Key>6XBNX-4JQGW-QX6QG-74P76-72V67</Key> -->\r\n                    <WillShowUI>OnError</WillShowUI>\r\n                </ProductKey>\r\n                <AcceptEula>true</AcceptEula>\r\n                <FullName>Vagrant</FullName>\r\n                <Organization>Vagrant</Organization>\r\n            </UserData>\r\n        </component>\r\n    </settings>\r\n    <settings pass=\"specialize\">\r\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <OEMInformation>\r\n                <HelpCustomized>false</HelpCustomized>\r\n            </OEMInformation>\r\n            <ComputerName>vagrant-2022</ComputerName>\r\n            <TimeZone>Pacific Standard Time</TimeZone>\r\n            <RegisteredOwner/>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-ServerManager-SvrMgrNc\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <DoNotOpenServerManagerAtLogon>true</DoNotOpenServerManagerAtLogon>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-IE-ESC\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <IEHardenAdmin>false</IEHardenAdmin>\r\n            <IEHardenUser>false</IEHardenUser>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-OutOfBoxExperience\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <DoNotOpenInitialConfigurationTasksAtLogon>true</DoNotOpenInitialConfigurationTasksAtLogon>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-Security-SPP-UX\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <SkipAutoActivation>true</SkipAutoActivation>\r\n        </component>\r\n        <component name=\"Microsoft-Windows-Deployment\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <RunSynchronous>\r\n                <RunSynchronousCommand wcm:action=\"add\">\r\n                    <Order>1</Order>\r\n                    <Description>Set Execution Policy 64 Bit</Description>\r\n                    <Path>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</Path>\r\n                </RunSynchronousCommand>\r\n                <RunSynchronousCommand wcm:action=\"add\">\r\n                    <Order>2</Order>\r\n                    <Description>Set Execution Policy 32 Bit</Description>\r\n                    <Path>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</Path>\r\n                </RunSynchronousCommand>\r\n                <RunSynchronousCommand wcm:action=\"add\">\r\n                    <Order>3</Order>\r\n                    <Description>Disable WinRM</Description>\r\n                    <Path>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-winrm.ps1</Path>\r\n                </RunSynchronousCommand>\r\n            </RunSynchronous>\r\n        </component>\r\n    </settings>\r\n    <settings pass=\"oobeSystem\">\r\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <AutoLogon>\r\n                <Password>\r\n                    <Value>vagrant</Value>\r\n                    <PlainText>true</PlainText>\r\n                </Password>\r\n                <Enabled>true</Enabled>\r\n                <Username>vagrant</Username>\r\n            </AutoLogon>\r\n            <FirstLogonCommands>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\r\n                    <Description>Set Execution Policy 64 Bit</Description>\r\n                    <Order>1</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>C:\\Windows\\SysWOW64\\cmd.exe /c powershell -Command \"Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force\"</CommandLine>\r\n                    <Description>Set Execution Policy 32 Bit</Description>\r\n                    <Order>2</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-winrm.ps1</CommandLine>\r\n                    <Description>Disable WinRM</Description>\r\n                    <Order>3</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>\r\n                    <Order>4</Order>\r\n                    <Description>Show file extensions in Explorer</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\Console /v QuickEdit /t REG_DWORD /d 1 /f</CommandLine>\r\n                    <Order>5</Order>\r\n                    <Description>Enable QuickEdit mode</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v Start_ShowRun /t REG_DWORD /d 1 /f</CommandLine>\r\n                    <Order>6</Order>\r\n                    <Description>Show Run command in Start Menu</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\ /v StartMenuAdminTools /t REG_DWORD /d 1 /f</CommandLine>\r\n                    <Order>7</Order>\r\n                    <Description>Show Administrative Tools in Start Menu</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateFileSizePercent /t REG_DWORD /d 0 /f</CommandLine>\r\n                    <Order>8</Order>\r\n                    <Description>Zero Hibernation File</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>%SystemRoot%\\System32\\reg.exe ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Power\\ /v HibernateEnabled /t REG_DWORD /d 0 /f</CommandLine>\r\n                    <Order>9</Order>\r\n                    <Description>Disable Hibernation Mode</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c wmic useraccount where \"name='vagrant'\" set PasswordExpires=FALSE</CommandLine>\r\n                    <Order>10</Order>\r\n                    <Description>Disable password expiration for vagrant user</Description>\r\n                </SynchronousCommand>\r\n                <!-- WITHOUT WINDOWS UPDATES -->\r\n                <!--\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\enable-winrm.ps1</CommandLine>\r\n                    <Description>Enable WinRM</Description>\r\n                    <Order>99</Order>\r\n                </SynchronousCommand>\r\n                -->\r\n                <!-- END WITHOUT WINDOWS UPDATES -->\r\n                <!-- WITH WINDOWS UPDATES -->\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c a:\\microsoft-updates.bat</CommandLine>\r\n                    <Order>98</Order>\r\n                    <Description>Enable Microsoft Updates</Description>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\disable-screensaver.ps1</CommandLine>\r\n                    <Description>Disable Screensaver</Description>\r\n                    <Order>99</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <SynchronousCommand wcm:action=\"add\">\r\n                    <CommandLine>cmd.exe /c C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File a:\\win-updates.ps1</CommandLine>\r\n                    <Description>Install Windows Updates</Description>\r\n                    <Order>100</Order>\r\n                    <RequiresUserInput>true</RequiresUserInput>\r\n                </SynchronousCommand>\r\n                <!-- END WITH WINDOWS UPDATES -->\r\n            </FirstLogonCommands>\r\n            <OOBE>\r\n                <HideEULAPage>true</HideEULAPage>\r\n                <HideLocalAccountScreen>true</HideLocalAccountScreen>\r\n                <HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>\r\n                <HideOnlineAccountScreens>true</HideOnlineAccountScreens>\r\n                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\r\n                <NetworkLocation>Home</NetworkLocation>\r\n                <ProtectYourPC>1</ProtectYourPC>\r\n            </OOBE>\r\n            <UserAccounts>\r\n                <AdministratorPassword>\r\n                    <Value>vagrant</Value>\r\n                    <PlainText>true</PlainText>\r\n                </AdministratorPassword>\r\n                <LocalAccounts>\r\n                    <LocalAccount wcm:action=\"add\">\r\n                        <Password>\r\n                            <Value>vagrant</Value>\r\n                            <PlainText>true</PlainText>\r\n                        </Password>\r\n                        <Group>administrators</Group>\r\n                        <DisplayName>Vagrant</DisplayName>\r\n                        <Name>vagrant</Name>\r\n                        <Description>Vagrant User</Description>\r\n                    </LocalAccount>\r\n                </LocalAccounts>\r\n            </UserAccounts>\r\n            <RegisteredOwner />\r\n        </component>\r\n    </settings>\r\n    <settings pass=\"offlineServicing\">\r\n        <component name=\"Microsoft-Windows-LUA-Settings\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <EnableLUA>false</EnableLUA>\r\n        </component>\r\n    </settings>\r\n    <cpi:offlineImage cpi:source=\"wim:c:/wim/install.wim#Windows Server 2012 R2 SERVERSTANDARD\" xmlns:cpi=\"urn:schemas-microsoft-com:cpi\" />\r\n</unattend>\r\n"
  },
  {
    "path": "packer/vagrant/build_all.sh",
    "content": "#!/bin/bash\n\nbash build_windows_10.sh\n# bash build_windows_11.sh # not ready yet\nbash build_windows_2019.sh\n# bash build_windows_2022.sh # not ready yet"
  },
  {
    "path": "packer/vagrant/build_windows_10.sh",
    "content": "#!/bin/bash\n\necho \"build vmware windows 10 box\"\npacker build --only=vmware-iso \\\n   --var iso_url=~/Téléchargements/19045.2006.220908-0225.22h2_release_svc_refresh_CLIENTENTERPRISEEVAL_OEMRET_x64FRE_en-us.iso \\\n  windows_10.json\n\necho \"build virtualbox windows 10 box\"\npacker build --only=virtualbox-iso \\\n  --var iso_url=~/Téléchargements/19045.2006.220908-0225.22h2_release_svc_refresh_CLIENTENTERPRISEEVAL_OEMRET_x64FRE_en-us.iso \\\n  windows_10.json\n\n"
  },
  {
    "path": "packer/vagrant/build_windows_11.sh",
    "content": "#!/bin/bash\n\necho \"build vmware windows 11 box\"\npacker build --only=vmware-iso \\\n  --var iso_url=~/Téléchargements/22621.525.220925-0207.ni_release_svc_refresh_CLIENTENTERPRISEEVAL_OEMRET_x64FRE_en-us.iso \\\n  windows_11.json\n\necho \"build virtualbox windows 11 box\"\npacker build --only=virtualbox-iso \\\n  --var iso_url=~/Téléchargements/22621.525.220925-0207.ni_release_svc_refresh_CLIENTENTERPRISEEVAL_OEMRET_x64FRE_en-us.iso \\\n  windows_11.json"
  },
  {
    "path": "packer/vagrant/build_windows_2019.sh",
    "content": "#!/bin/bash\n\n# ISO link :\n# https://software-static.download.prss.microsoft.com/dbazure/988969d5-f34g-4e03-ac9d-1f9786c66749/17763.3650.221105-1748.rs5_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso\n\necho \"build vmware windows server 2019 box\"\npacker build \\\n  --only=vmware-iso \\\n  --var vhv_enable=true \\\n  --var iso_url=~/Téléchargements/17763.3650.221105-1748.rs5_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso \\\n  windows_2019.json\n\necho \"build virtualbox windows server 2019 box\"\npacker build \\\n  --only=virtualbox-iso \\\n  --var vhv_enable=true \\\n  --var iso_url=~/Téléchargements/17763.3650.221105-1748.rs5_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso \\\n  windows_2019.json\n"
  },
  {
    "path": "packer/vagrant/build_windows_2022.sh",
    "content": "#!/bin/bash\n\npacker build \\\n  --only=vmware-iso \\\n  --var vhv_enable=true \\\n  --var iso_url=~/Downloads/20348.169.210806-2348.fe_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso  \\\n  windows_2022_core.json\n"
  },
  {
    "path": "packer/vagrant/scripts/compile-dotnet-assemblies.bat",
    "content": "::http://support.microsoft.com/kb/2570538\n::http://robrelyea.wordpress.com/2007/07/13/may-be-helpful-ngen-exe-executequeueditems/\n\nif \"%PROCESSOR_ARCHITECTURE%\"==\"AMD64\" goto 64BIT\n\n%windir%\\microsoft.net\\framework\\v4.0.30319\\ngen.exe update /force /queue > NUL\n%windir%\\microsoft.net\\framework\\v4.0.30319\\ngen.exe executequeueditems > NUL\n\nexit 0\n\n:64BIT\n%windir%\\microsoft.net\\framework\\v4.0.30319\\ngen.exe update /force /queue > NUL\n%windir%\\microsoft.net\\framework64\\v4.0.30319\\ngen.exe update /force /queue > NUL\n%windir%\\microsoft.net\\framework\\v4.0.30319\\ngen.exe executequeueditems > NUL\n%windir%\\microsoft.net\\framework64\\v4.0.30319\\ngen.exe executequeueditems > NUL\n\nexit 0\n"
  },
  {
    "path": "packer/vagrant/scripts/dis-updates.bat",
    "content": "rem http://www.windows-commandline.com/disable-automatic-updates-command-line/\nreg add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\" /v AUOptions /t REG_DWORD /d 1 /f\n\nrem remove optional WSUS server settings\nreg delete \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Microsoft\\Windows\\WindowsUpdate\" /f\n\nrem even harder, disable windows update service\nrem sc config wuauserv start= disabled\nrem net stop wuauserv\nset logfile=C:\\Windows\\Temp\\win-updates.log\n\nif exist %logfile% (\n  echo Show Windows Updates log file %logfile%\n  dir %logfile%\n  type %logfile%\n  rem output of type command is not fully shown in packer/ssh session, so try PowerShell\n  rem but it will hang if log file is about 22 KByte\n  rem powershell -command \"Get-Content %logfile%\"\n  echo End of Windows Updates log file %logfile%\n)\n"
  },
  {
    "path": "packer/vagrant/scripts/disable-screensaver.ps1",
    "content": "Write-Output \"Disabling Screensaver\"\nSet-ItemProperty \"HKCU:\\Control Panel\\Desktop\" -Name ScreenSaveActive -Value 0 -Type DWord\n& powercfg -x -monitor-timeout-ac 0\n& powercfg -x -monitor-timeout-dc 0\n"
  },
  {
    "path": "packer/vagrant/scripts/disable-winrm.ps1",
    "content": "netsh advfirewall firewall set rule name=\"Windows Remote Management (HTTP-In)\" new enable=yes action=block\nnetsh advfirewall firewall set rule group=\"Windows Remote Management\" new enable=yes\n$winrmService = Get-Service -Name WinRM\nif ($winrmService.Status -eq \"Running\") {\n  Disable-PSRemoting -Force\n}\nStop-Service winrm\nSet-Service -Name winrm -StartupType Disabled\n"
  },
  {
    "path": "packer/vagrant/scripts/enable-rdp.bat",
    "content": "netsh advfirewall firewall add rule name=\"Open Port 3389\" dir=in action=allow protocol=TCP localport=3389\nreg add \"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\" /v fDenyTSConnections /t REG_DWORD /d 0 /f\n"
  },
  {
    "path": "packer/vagrant/scripts/enable-winrm.ps1",
    "content": "Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory Private\n\nEnable-PSRemoting -Force\nwinrm quickconfig -q\nwinrm quickconfig -transport:http\nwinrm set winrm/config '@{MaxTimeoutms=\"1800000\"}'\nwinrm set winrm/config/winrs '@{MaxMemoryPerShellMB=\"800\"}'\nwinrm set winrm/config/service '@{AllowUnencrypted=\"true\"}'\nwinrm set winrm/config/service/auth '@{Basic=\"true\"}'\nwinrm set winrm/config/client/auth '@{Basic=\"true\"}'\nwinrm set winrm/config/listener?Address=*+Transport=HTTP '@{Port=\"5985\"}'\nnetsh advfirewall firewall set rule group=\"Windows Remote Administration\" new enable=yes\nnetsh advfirewall firewall set rule name=\"Windows Remote Management (HTTP-In)\" new enable=yes action=allow remoteip=any\nSet-Service winrm -startuptype \"auto\"\nRestart-Service winrm\n"
  },
  {
    "path": "packer/vagrant/scripts/fixnetwork.ps1",
    "content": "﻿# You cannot enable Windows PowerShell Remoting on network connections that are set to Public\n# Spin through all the network locations and if they are set to Public, set them to Private\n# using the INetwork interface:\n# http://msdn.microsoft.com/en-us/library/windows/desktop/aa370750(v=vs.85).aspx\n# For more info, see:\n# http://blogs.msdn.com/b/powershell/archive/2009/04/03/setting-network-location-to-private.aspx\n\nfunction Set-NetworkTypeToPrivate {\n  [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPositionalParameters', '')]\n  param()\n  # Network location feature was only introduced in Windows Vista - no need to bother with this\n  # if the operating system is older than Vista\n  if ([environment]::OSVersion.version.Major -lt 6) { return }\n\n  # You cannot change the network location if you are joined to a domain, so abort\n  if (1, 3, 4, 5 -contains (Get-CimInstance win32_computersystem).DomainRole) { return }\n\n  # Get network connections\n  $networkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]\"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}\"))\n  $connections = $networkListManager.GetNetworkConnections()\n\n  $connections | ForEach-Object {\n    Write-Output $_.GetNetwork().GetName() \"category was previously set to\" $_.GetNetwork().GetCategory()\n    #$_.GetNetwork().SetCategory(1)\n    Write-Output $_.GetNetwork().GetName() \"changed to category\" $_.GetNetwork().GetCategory()\n  }\n\n}\n\nSet-NetworkTypeToPrivate\n"
  },
  {
    "path": "packer/vagrant/scripts/microsoft-updates.bat",
    "content": "net stop wuauserv\n\nreg add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\" /v EnableFeaturedSoftware /t REG_DWORD /d 1 /f\n\nreg add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update\" /v IncludeRecommendedUpdates /t REG_DWORD /d 1 /f\n\necho Set ServiceManager = CreateObject(\"Microsoft.Update.ServiceManager\") > A:\\temp.vbs\necho Set NewUpdateService = ServiceManager.AddService2(\"7971f918-a847-4430-9279-4a52d1efe18d\",7,\"\") >> A:\\temp.vbs\n\ncscript A:\\temp.vbs\n\nnet start wuauserv\n"
  },
  {
    "path": "packer/vagrant/scripts/set-powerplan.ps1",
    "content": "﻿Try {\n  Write-Output \"Set power plan to high performance\"\n\n  $HighPerf = powercfg -l | ForEach-Object { if ($_.contains(\"High performance\")) { $_.split()[3] } }\n\n  # $HighPerf cannot be $null, we try activate this power profile with powercfg\n  if ($null -eq $HighPerf) {\n    throw \"Error: HighPerf is null\"\n  }\n\n  $CurrPlan = $(powercfg -getactivescheme).split()[3]\n\n  if ($CurrPlan -ne $HighPerf) { powercfg -setactive $HighPerf }\n\n}\nCatch {\n  Write-Warning -Message \"Unable to set power plan to high performance\"\n  Write-Warning $Error[0]\n}\n"
  },
  {
    "path": "packer/vagrant/scripts/set-winrm-automatic.bat",
    "content": "echo Set WinRM start type to auto\nsc config winrm start= auto\n"
  },
  {
    "path": "packer/vagrant/scripts/sysprep.bat",
    "content": "rem net stop tiledatamodelsvc\nif exist a:\\unattend.xml (\n  c:\\windows\\system32\\sysprep\\sysprep.exe /generalize /oobe /shutdown /unattend:a:\\unattend.xml\n) else (\n  del /F \\Windows\\System32\\Sysprep\\unattend.xml\n  c:\\windows\\system32\\sysprep\\sysprep.exe /generalize /oobe /shutdown /quiet  \n)\n"
  },
  {
    "path": "packer/vagrant/scripts/uac-enable.bat",
    "content": "reg add \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\" /f /v EnableLUA /t REG_DWORD /d 1\n"
  },
  {
    "path": "packer/vagrant/scripts/unattend.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<unattend xmlns=\"urn:schemas-microsoft-com:unattend\">\r\n    <settings pass=\"generalize\">\r\n        <component name=\"Microsoft-Windows-Security-SPP\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <SkipRearm>0</SkipRearm>\r\n        </component>\r\n        <!--\r\n        <component name=\"Microsoft-Windows-PnpSysprep\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <PersistAllDeviceInstalls>false</PersistAllDeviceInstalls>\r\n            <DoNotCleanUpNonPresentDevices>false</DoNotCleanUpNonPresentDevices>\r\n        </component>\r\n        -->\r\n    </settings>\r\n    <settings pass=\"oobeSystem\">\r\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <OOBE>\r\n                <HideEULAPage>true</HideEULAPage>\r\n                <ProtectYourPC>3</ProtectYourPC>\r\n                <NetworkLocation>Work</NetworkLocation>\r\n                <HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>\r\n                <SkipUserOOBE>true</SkipUserOOBE>\r\n                <SkipMachineOOBE>true</SkipMachineOOBE>\r\n            </OOBE>\r\n            <AutoLogon>\r\n                <Password>\r\n                    <Value>vagrant</Value>\r\n                    <PlainText>true</PlainText>\r\n                </Password>\r\n                <Enabled>true</Enabled>\r\n                <LogonCount>1</LogonCount>\r\n                <Username>vagrant</Username>\r\n            </AutoLogon>\r\n        </component>\r\n    </settings>\r\n    <settings pass=\"specialize\">\r\n        <component name=\"Microsoft-Windows-Shell-Setup\" processorArchitecture=\"amd64\" publicKeyToken=\"31bf3856ad364e35\" language=\"neutral\" versionScope=\"nonSxS\" xmlns:wcm=\"http://schemas.microsoft.com/WMIConfig/2002/State\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n            <ComputerName>vagrant</ComputerName>\r\n            <CopyProfile>false</CopyProfile>\r\n        </component>\r\n    </settings>\r\n</unattend>\r\n"
  },
  {
    "path": "packer/vagrant/scripts/vm-guest-tools.ps1",
    "content": "﻿if (!( Test-Path \"C:\\Windows\\Temp\\7z1900-x64.msi\")) {\n  [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('https://www.7-zip.org/a/7z1900-x64.msi', 'C:\\Windows\\Temp\\7z1900-x64.msi')\n}\nif (!(Test-Path \"C:\\Windows\\Temp\\7z1900-x64.msi\")) {\n  Start-Sleep 5; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('https://www.7-zip.org/a/7z1900-x64.msi', 'C:\\Windows\\Temp\\7z1900-x64.msi')\n}\ncmd /c msiexec /qb /i C:\\Windows\\Temp\\7z1900-x64.msi\n\nif (\"$env:PACKER_BUILDER_TYPE\" -eq \"vmware-iso\") {\n\n  Write-Output \"Using VMware\"\n  if (Test-Path \"C:\\Users\\vagrant\\windows.iso\") {\n    Move-Item -force C:\\Users\\vagrant\\windows.iso C:\\Windows\\Temp\n  }\n\n  if (!(Test-Path \"C:\\Windows\\Temp\\windows.iso\")) {\n    Try {\n      # Disabling the progress bar speeds up IWR https://github.com/PowerShell/PowerShell/issues/2138\n      $ProgressPreference = 'SilentlyContinue'\n      $pageContentLinks = (Invoke-WebRequest('https://softwareupdate.vmware.com/cds/vmw-desktop/ws') -UseBasicParsing).Links | where-object { $_.href -Match \"[0-9]\" } | Select-Object href | ForEach-Object { $_.href.Trim('/') }\n      $versionObject = $pageContentLinks | ForEach-Object { new-object System.Version ($_) } | sort-object -Descending | select-object -First 1 -Property:Major, Minor, Build\n      $newestVersion = $versionObject.Major.ToString() + \".\" + $versionObject.Minor.ToString() + \".\" + $versionObject.Build.ToString() | out-string\n      $newestVersion = $newestVersion.TrimEnd(\"`r?`n\")\n\n      $nextURISubdirectoryObject = (Invoke-WebRequest(\"https://softwareupdate.vmware.com/cds/vmw-desktop/ws/$newestVersion/\") -UseBasicParsing).Links | where-object { $_.href -Match \"[0-9]\" } | Select-Object href | where-object { $_.href -Match \"[0-9]\" }\n      $nextUriSubdirectory = $nextURISubdirectoryObject.href | Out-String\n      $nextUriSubdirectory = $nextUriSubdirectory.TrimEnd(\"`r?`n\")\n      $newestVMwareToolsURL = \"https://softwareupdate.vmware.com/cds/vmw-desktop/ws/$newestVersion/$nextURISubdirectory/windows/packages/tools-windows.tar\"\n      Write-Output \"The latest version of VMware tools has been determined to be downloadable from $newestVMwareToolsURL\"\n      [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile(\"$newestVMwareToolsURL\", 'C:\\Windows\\Temp\\vmware-tools.tar')\n    }\n    Catch {\n      Write-Output \"Unable to determine the latest version of VMware tools. Falling back to hardcoded URL.\"\n      (New-Object System.Net.WebClient).DownloadFile('https://softwareupdate.vmware.com/cds/vmw-desktop/ws/15.5.5/16285975/windows/packages/tools-windows.tar', 'C:\\Windows\\Temp\\vmware-tools.tar')\n    }\n    cmd /c \"C:\\PROGRA~1\\7-Zip\\7z.exe\" x C:\\Windows\\Temp\\vmware-tools.tar -oC:\\Windows\\Temp\n    Move-Item c:\\windows\\temp\\VMware-tools-windows-*.iso c:\\windows\\temp\\windows.iso\n    Try { Remove-Item \"C:\\Program Files (x86)\\VMWare\" -Recurse -Force -ErrorAction Stop } Catch { Write-Output \"Directory didn't exist to be removed.\" }\n  }\n\n  cmd /c \"C:\\PROGRA~1\\7-Zip\\7z.exe\" x \"C:\\Windows\\Temp\\windows.iso\" -oC:\\Windows\\Temp\\VMWare\n  cmd /c C:\\Windows\\Temp\\VMWare\\setup.exe /S /v\"/qn REBOOT=R\\\"\n\n  Remove-Item -Force \"C:\\Windows\\Temp\\vmware-tools.tar\"\n  Remove-Item -Force \"C:\\Windows\\Temp\\windows.iso\"\n  Remove-Item -Force -Recurse \"C:\\Windows\\Temp\\VMware\"\n}\n\nif (\"$env:PACKER_BUILDER_TYPE\" -eq \"virtualbox-iso\") {\n  Write-Output \"Using Virtualbox\"\n  if (Test-Path \"C:\\Users\\vagrant\\VBoxGuestAdditions.iso\") {\n    Move-Item -Force C:\\Users\\vagrant\\VBoxGuestAdditions.iso C:\\Windows\\Temp\n  }\n\n  if (!(Test-Path \"C:\\Windows\\Temp\\VBoxGuestAdditions.iso\")) {\n    Try {\n      $pageContentLinks = (Invoke-WebRequest('https://download.virtualbox.org/virtualbox') -UseBasicParsing).Links | where-object { $_.href -Match \"[0-9]\" } | Select-Object href |  where-object { $_.href -NotMatch \"BETA\" } |  where-object { $_.href -NotMatch \"RC\" } |   where-object { $_.href -Match \"[0-9]\\.[0-9]\" } | ForEach-Object { $_.href.Trim('/') }\n      $versionObject = $pageContentLinks | ForEach-Object { new-object System.Version ($_) } | sort-object -Descending | select-object -First 1 -Property:Major, Minor, Build\n      $newestVersion = $versionObject.Major.ToString() + \".\" + $versionObject.Minor.ToString() + \".\" + $versionObject.Build.ToString() | out-string\n      $newestVersion = $newestVersion.TrimEnd(\"`r?`n\")\n\n      $nextURISubdirectoryObject = (Invoke-WebRequest(\"https://download.virtualbox.org/virtualbox/$newestVersion/\") -UseBasicParsing).Links | Select-Object href | where-object { $_.href -Match \"GuestAdditions\" }\n      $nextUriSubdirectory = $nextURISubdirectoryObject.href | Out-String\n      $nextUriSubdirectory = $nextUriSubdirectory.TrimEnd(\"`r?`n\")\n      $newestVboxToolsURL = \"https://download.virtualbox.org/virtualbox/$newestVersion/$nextUriSubdirectory\"\n      Write-Output \"The latest version of VirtualBox tools has been determined to be downloadable from $newestVboxToolsURL\"\n      [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile(\"$newestVboxToolsURL\", 'C:\\Windows\\Temp\\VBoxGuestAdditions.iso')\n    }\n    Catch {\n      Write-Output \"Unable to determine the latest version of VBox tools. Falling back to hardcoded URL.\"\n      [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (New-Object System.Net.WebClient).DownloadFile('https://download.virtualbox.org/virtualbox/6.1.8/VBoxGuestAdditions_6.1.8.iso', 'C:\\Windows\\Temp\\VBoxGuestAdditions.iso')\n    }\n  }\n\n  cmd /c \"\"C:\\PROGRA~1\\7-Zip\\7z.exe\" x C:\\Windows\\Temp\\VBoxGuestAdditions.iso -oC:\\Windows\\Temp\\virtualbox\"\n  Get-ChildItem \"C:\\Windows\\Temp\\virtualbox\\cert\\\" -Filter vbox*.cer | Foreach-Object { C:\\Windows\\Temp\\virtualbox\\cert\\VBoxCertUtil add-trusted-publisher $_.FullName --root $_.FullName }\n  cmd /c C:\\Windows\\Temp\\virtualbox\\VBoxWindowsAdditions.exe /S\n  cmd /c rd /S /Q \"C:\\Windows\\Temp\\virtualbox\"\n}\n\nif (\"$env:PACKER_BUILDER_TYPE\" -eq \"parallels-iso\") {\n  Write-Output \"Using Parallels Desktop\"\n  # This is required when using Parallels Desktop\n  # Currently the installation of Parallels Tools is broken if you're installing in Windows Server & Windows Server Core\n  # You will encounter an error in printui.dll module not found message.\n  # This feature will add the required libraries for printing services.\n\n  # Parallels Tools is required for sync_folder to work.\n  # Vagrantfile config: v.update_guest_tools = true will be installed with no issues\n  if ($(Get-ItemProperty \"HKLM:\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\").ProductName.StartsWith(\"Windows Server\")) {\n    Write-Output \"Installing Print Server service\"\n    Install-WindowsFeature -Name Print-Server\n  }  \n}\n\ncmd /c msiexec /qb /x C:\\Windows\\Temp\\7z1900-x64.msi\n"
  },
  {
    "path": "packer/vagrant/scripts/win-updates.ps1",
    "content": "[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '')]\r\nparam($global:RestartRequired = 0,\r\n  $global:MoreUpdates = 0,\r\n  $global:MaxCycles = 5,\r\n  $MaxUpdatesPerCycle = 500,\r\n  $BeginWithRestart = 0)\r\n\r\n$Logfile = \"C:\\Windows\\Temp\\win-updates.log\"\r\n\r\nfunction LogWrite {\r\n  Param ([string]$logstring)\r\n  $now = Get-Date -format s\r\n  Add-Content $Logfile -value \"$now $logstring\"\r\n  Write-Output $logstring\r\n}\r\n\r\nfunction Check-ContinueRestartOrEnd() {\r\n  $RegistryKey = \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\"\r\n  $RegistryEntry = \"InstallWindowsUpdates\"\r\n  switch ($global:RestartRequired) {\r\n    0 {\r\n      $prop = (Get-ItemProperty $RegistryKey).$RegistryEntry\r\n      if ($prop) {\r\n        LogWrite \"Restart Registry Entry Exists - Removing It\"\r\n        Remove-ItemProperty -Path $RegistryKey -Name $RegistryEntry -ErrorAction SilentlyContinue\r\n      }\r\n\r\n      LogWrite \"No Restart Required\"\r\n      Check-WindowsUpdates\r\n\r\n      if (($global:MoreUpdates -eq 1) -and ($script:Cycles -le $global:MaxCycles)) {\r\n        Install-WindowsUpdates\r\n      }\r\n      elseif ($script:Cycles -gt $global:MaxCycles) {\r\n        LogWrite \"Exceeded Cycle Count - Stopping\"\r\n        & \"a:\\enable-winrm.ps1\"\r\n      }\r\n      else {\r\n        LogWrite \"Done Installing Windows Updates\"\r\n        & \"a:\\enable-winrm.ps1\"\r\n      }\r\n    }\r\n    1 {\r\n      $prop = (Get-ItemProperty $RegistryKey).$RegistryEntry\r\n      if (-not $prop) {\r\n        LogWrite \"Restart Registry Entry Does Not Exist - Creating It\"\r\n        Set-ItemProperty -Path $RegistryKey -Name $RegistryEntry -Value \"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -File $($script:ScriptPath) -MaxUpdatesPerCycle $($MaxUpdatesPerCycle)\"\r\n      }\r\n      else {\r\n        LogWrite \"Restart Registry Entry Exists Already\"\r\n      }\r\n\r\n      LogWrite \"Restart Required - Restarting...\"\r\n      Restart-Computer\r\n    }\r\n    default {\r\n      LogWrite \"Unsure If A Restart Is Required\"\r\n      break\r\n    }\r\n  }\r\n}\r\n\r\nfunction Install-WindowsUpdates()\r\n {\r\n  [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]\r\n  [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')]\r\n  param()\r\n  $script:Cycles++\r\n  LogWrite \"Evaluating Available Updates with limit of $($MaxUpdatesPerCycle):\"\r\n  $UpdatesToDownload = New-Object -ComObject 'Microsoft.Update.UpdateColl'\r\n  $script:i = 0;\r\n  $CurrentUpdates = $SearchResult.Updates\r\n  while ($script:i -lt $CurrentUpdates.Count -and $script:CycleUpdateCount -lt $MaxUpdatesPerCycle) {\r\n    $Update = $CurrentUpdates.Item($script:i)\r\n    if ($null -ne $Update) {\r\n      [bool]$addThisUpdate = $false\r\n      if ($Update.InstallationBehavior.CanRequestUserInput) {\r\n        LogWrite \"> Skipping: $($Update.Title) because it requires user input\"\r\n      }\r\n      else {\r\n        if (!($Update.EulaAccepted)) {\r\n          LogWrite \"> Note: $($Update.Title) has a license agreement that must be accepted. Accepting the license.\"\r\n          $Update.AcceptEula()\r\n          [bool]$addThisUpdate = $true\r\n          $script:CycleUpdateCount++\r\n        }\r\n        else {\r\n          [bool]$addThisUpdate = $true\r\n          $script:CycleUpdateCount++\r\n        }\r\n      }\r\n\r\n      if ([bool]$addThisUpdate) {\r\n        LogWrite \"Adding: $($Update.Title)\"\r\n        $UpdatesToDownload.Add($Update) | Out-Null\r\n      }\r\n    }\r\n    $script:i++\r\n  }\r\n\r\n  if ($UpdatesToDownload.Count -eq 0) {\r\n    LogWrite \"No Updates To Download...\"\r\n  }\r\n  else {\r\n    LogWrite 'Downloading Updates...'\r\n    $ok = 0;\r\n    while (! $ok) {\r\n      try {\r\n        $Downloader = $UpdateSession.CreateUpdateDownloader()\r\n        $Downloader.Updates = $UpdatesToDownload\r\n        $Downloader.Download()\r\n        $ok = 1;\r\n      }\r\n      catch {\r\n        LogWrite $_.Exception | Format-List -force\r\n        LogWrite \"Error downloading updates. Retrying in 30s.\"\r\n        $script:attempts = $script:attempts + 1\r\n        Start-Sleep -s 30\r\n      }\r\n    }\r\n  }\r\n\r\n  $UpdatesToInstall = New-Object -ComObject 'Microsoft.Update.UpdateColl'\r\n  [bool]$rebootMayBeRequired = $false\r\n  LogWrite 'The following updates are downloaded and ready to be installed:'\r\n  foreach ($Update in $SearchResult.Updates) {\r\n    if (($Update.IsDownloaded)) {\r\n      LogWrite \"> $($Update.Title)\"\r\n      $UpdatesToInstall.Add($Update) | Out-Null\r\n\r\n      if ($Update.InstallationBehavior.RebootBehavior -gt 0) {\r\n        [bool]$rebootMayBeRequired = $true\r\n      }\r\n    }\r\n  }\r\n\r\n  if ($UpdatesToInstall.Count -eq 0) {\r\n    LogWrite 'No updates available to install...'\r\n    $global:MoreUpdates = 0\r\n    $global:RestartRequired = 0\r\n    & \"a:\\enable-winrm.ps1\"\r\n    break\r\n  }\r\n\r\n  if ($rebootMayBeRequired) {\r\n    LogWrite 'These updates may require a reboot'\r\n    $global:RestartRequired = 1\r\n  }\r\n\r\n  LogWrite 'Installing updates...'\r\n\r\n  $Installer = $script:UpdateSession.CreateUpdateInstaller()\r\n  $Installer.Updates = $UpdatesToInstall\r\n  $InstallationResult = $Installer.Install()\r\n\r\n  LogWrite \"Installation Result: $($InstallationResult.ResultCode)\"\r\n  LogWrite \"Reboot Required: $($InstallationResult.RebootRequired)\"\r\n  LogWrite 'Listing of updates installed and individual installation results:'\r\n  if ($InstallationResult.RebootRequired) {\r\n    $global:RestartRequired = 1\r\n  }\r\n  else {\r\n    $global:RestartRequired = 0\r\n  }\r\n\r\n  for ($i = 0; $i -lt $UpdatesToInstall.Count; $i++) {\r\n    New-Object -TypeName PSObject -Property @{\r\n      Title  = $UpdatesToInstall.Item($i).Title\r\n      Result = $InstallationResult.GetUpdateResult($i).ResultCode\r\n    }\r\n    LogWrite \"Item: $($UpdatesToInstall.Item($i).Title)\"\r\n    LogWrite \"Result: $($InstallationResult.GetUpdateResult($i).ResultCode)\"\r\n  }\r\n\r\n  Check-ContinueRestartOrEnd\r\n}\r\n\r\nfunction Check-WindowsUpdates() {\r\n  [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]\r\n  [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '')]\r\n  param()\r\n  LogWrite \"Checking For Windows Updates\"\r\n  $Username = $env:USERDOMAIN + \"\\\" + $env:USERNAME\r\n  LogWrite \"Script: $script:ScriptPath `nScript User: $Username `nStarted: $(Get-Date)\"\r\n\r\n  $script:UpdateSearcher = $script:UpdateSession.CreateUpdateSearcher()\r\n  $script:successful = $FALSE\r\n  $script:attempts = 0\r\n  $script:maxAttempts = 12\r\n  while (-not $script:successful -and $script:attempts -lt $script:maxAttempts) {\r\n    try {\r\n      $script:SearchResult = $script:UpdateSearcher.Search(\"IsInstalled=0 and Type='Software' and IsHidden=0\")\r\n      $script:successful = $TRUE\r\n    }\r\n    catch {\r\n      LogWrite $_.Exception | Format-List -force\r\n      LogWrite \"Search call to UpdateSearcher was unsuccessful. Retrying in 10s.\"\r\n      $script:attempts = $script:attempts + 1\r\n      Start-Sleep -s 10\r\n    }\r\n  }\r\n\r\n  if ($SearchResult.Updates.Count -ne 0) {\r\n    $Message = \"There are \" + $SearchResult.Updates.Count + \" more updates.\"\r\n    LogWrite $Message\r\n    try {\r\n      for ($i = 0; $i -lt $script:SearchResult.Updates.Count; $i++) {\r\n        LogWrite $script:SearchResult.Updates.Item($i).Title\r\n        LogWrite $script:SearchResult.Updates.Item($i).Description\r\n        LogWrite $script:SearchResult.Updates.Item($i).RebootRequired\r\n        LogWrite $script:SearchResult.Updates.Item($i).EulaAccepted\r\n      }\r\n      $global:MoreUpdates = 1\r\n    }\r\n    catch {\r\n      LogWrite $_.Exception | Format-List -force\r\n      LogWrite \"Showing SearchResult was unsuccessful. Rebooting.\"\r\n      $global:RestartRequired = 1\r\n      $global:MoreUpdates = 0\r\n      Check-ContinueRestartOrEnd\r\n      LogWrite \"Show never happen to see this text!\"\r\n      Restart-Computer\r\n    }\r\n  }\r\n  else {\r\n    LogWrite 'There are no applicable updates'\r\n    $global:RestartRequired = 0\r\n    $global:MoreUpdates = 0\r\n  }\r\n}\r\n\r\n$script:ScriptName = $MyInvocation.MyCommand.ToString()\r\n$script:ScriptPath = $MyInvocation.MyCommand.Path\r\n$script:UpdateSession = New-Object -ComObject 'Microsoft.Update.Session'\r\n$script:UpdateSession.ClientApplicationID = 'Packer Windows Update Installer'\r\n$script:UpdateSearcher = $script:UpdateSession.CreateUpdateSearcher()\r\n$script:SearchResult = New-Object -ComObject 'Microsoft.Update.UpdateColl'\r\n$script:Cycles = 0\r\n$script:CycleUpdateCount = 0\r\n\r\nif ($BeginWithRestart) {\r\n  $global:RestartRequired = 1\r\n  Check-ContinueRestartOrEnd\r\n}\r\n\r\nCheck-WindowsUpdates\r\nif ($global:MoreUpdates -eq 1) {\r\n  Install-WindowsUpdates\r\n}\r\nelse {\r\n  Check-ContinueRestartOrEnd\r\n}\r\n"
  },
  {
    "path": "packer/vagrant/vagrantfile-windows_10.template",
    "content": "# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.require_version \">= 1.6.2\"\n\nVagrant.configure(\"2\") do |config|\n    config.vm.define \"vagrant-windows-10-preview\"\n    config.vm.box = \"windows_10_preview\"\n    config.vm.communicator = \"winrm\"\n\n    # Admin user name and password\n    config.winrm.username = \"vagrant\"\n    config.winrm.password = \"vagrant\"\n\n    config.vm.guest = :windows\n    config.windows.halt_timeout = 15\n\n    config.vm.network :forwarded_port, guest: 3389, host: 3389, id: \"rdp\", auto_correct: true\n\n    config.vm.provider :virtualbox do |v, override|\n        #v.gui = true\n        v.customize [\"modifyvm\", :id, \"--memory\", 2048]\n        v.customize [\"modifyvm\", :id, \"--cpus\", 2]\n        v.customize [\"modifyvm\", :id, \"--vram\", 128]\n        v.customize [\"modifyvm\", :id, \"--clipboard\", \"bidirectional\"]\n        v.customize [\"setextradata\", \"global\", \"GUI/SuppressMessages\", \"all\" ]\n    end\n\n    config.vm.provider :vmware_fusion do |v, override|\n        v.gui = true\n        v.vmx[\"memsize\"] = \"2048\"\n        v.vmx[\"numvcpus\"] = \"2\"\n        v.vmx[\"ethernet0.virtualDev\"] = \"vmxnet3\"\n        v.vmx[\"RemoteDisplay.vnc.enabled\"] = \"false\"\n        v.vmx[\"RemoteDisplay.vnc.port\"] = \"5900\"\n        v.vmx[\"scsi0.virtualDev\"] = \"lsisas1068\"\n        v.vmx[\"gui.fitguestusingnativedisplayresolution\"] = \"TRUE\"\n        v.vmx[\"mks.enable3d\"] = \"TRUE\"\n        v.vmx[\"mks.forceDiscreteGPU\"] = \"TRUE\"\n        v.vmx[\"gui.fullscreenatpoweron\"] = \"TRUE\"\n        v.vmx[\"gui.viewmodeatpoweron\"] = \"fullscreen\"\n        v.vmx[\"gui.lastPoweredViewMode\"] = \"fullscreen\"\n        v.vmx[\"sound.startconnected\"] = \"FALSE\"\n        v.vmx[\"sound.present\"] = \"FALSE\"\n        v.vmx[\"sound.autodetect\"] = \"TRUE\"\n        v.enable_vmrun_ip_lookup = false\n        v.whitelist_verified = true\n        v.vmx[\"hgfs.linkRootShare\"] = \"FALSE\"\n    end\n\n    config.vm.provider :vmware_workstation do |v, override|\n        v.gui = true\n        v.vmx[\"memsize\"] = \"2048\"\n        v.vmx[\"numvcpus\"] = \"2\"\n        v.vmx[\"ethernet0.virtualDev\"] = \"vmxnet3\"\n        v.vmx[\"RemoteDisplay.vnc.enabled\"] = \"false\"\n        v.vmx[\"RemoteDisplay.vnc.port\"] = \"5900\"\n        v.vmx[\"scsi0.virtualDev\"] = \"lsisas1068\"\n        v.enable_vmrun_ip_lookup = false\n        v.whitelist_verified = true\n        v.vmx[\"hgfs.linkRootShare\"] = \"FALSE\"\n    end\n\n    config.vm.provider \"hyperv\" do |v|\n        v.cpus = 2\n        v.maxmemory = 2048\n        v.linked_clone = true\n    end\n    \n    config.vm.provider :libvirt do |libvirt, override|\n        libvirt.memory = 2048\n        libvirt.cpus = 2\n\n        # Use WinRM for the default synced folder; or disable it if\n        # WinRM is not available. Linux hosts don't support SMB,\n        # and Windows guests don't support NFS/9P/rsync\n        # See https://github.com/Cimpress-MCP/vagrant-winrm-syncedfolders\n        if Vagrant.has_plugin?(\"vagrant-winrm-syncedfolders\")\n            override.vm.synced_folder \".\", \"/vagrant\", type: \"winrm\"\n        else\n            override.vm.synced_folder \".\", \"/vagrant\", disabled: true\n        end\n\n        # Enable Hyper-V enlightments, see\n        # https://blog.wikichoon.com/2014/07/enabling-hyper-v-enlightenments-with-kvm.html\n        libvirt.hyperv_feature :name => 'stimer',  :state => 'on'\n        libvirt.hyperv_feature :name => 'relaxed', :state => 'on'\n        libvirt.hyperv_feature :name => 'vapic',   :state => 'on'\n        libvirt.hyperv_feature :name => 'synic',   :state => 'on'\n    end\nend\n"
  },
  {
    "path": "packer/vagrant/vagrantfile-windows_2016.template",
    "content": "# -*- mode: ruby -*-\n# vi: set ft=ruby :\n\nVagrant.require_version \">= 1.6.2\"\n\nVagrant.configure(\"2\") do |config|\n    config.vm.define \"vagrant-windows-2016\"\n    config.vm.box = \"windows_2016\"\n    config.vm.communicator = \"winrm\"\n\n    # Admin user name and password\n    config.winrm.username = \"vagrant\"\n    config.winrm.password = \"vagrant\"\n\n    config.vm.guest = :windows\n    config.windows.halt_timeout = 15\n\n    config.vm.network :forwarded_port, guest: 3389, host: 3389, id: \"rdp\", auto_correct: true\n\n    config.vm.provider :virtualbox do |v, override|\n        #v.gui = true\n        v.customize [\"modifyvm\", :id, \"--memory\", 2048]\n        v.customize [\"modifyvm\", :id, \"--cpus\", 2]\n        v.customize [\"modifyvm\", :id, \"--vram\", 128]\n        v.customize [\"modifyvm\", :id, \"--clipboard\", \"bidirectional\"]\n        v.customize [\"setextradata\", \"global\", \"GUI/SuppressMessages\", \"all\" ]\n    end\n\n    config.vm.provider :vmware_fusion do |v, override|\n        v.gui = true\n        v.vmx[\"memsize\"] = \"2048\"\n        v.vmx[\"numvcpus\"] = \"2\"\n        v.vmx[\"ethernet0.virtualDev\"] = \"vmxnet3\"\n        v.vmx[\"RemoteDisplay.vnc.enabled\"] = \"false\"\n        v.vmx[\"RemoteDisplay.vnc.port\"] = \"5900\"\n        v.vmx[\"scsi0.virtualDev\"] = \"lsisas1068\"\n        v.vmx[\"gui.fitguestusingnativedisplayresolution\"] = \"TRUE\"\n        v.vmx[\"mks.enable3d\"] = \"TRUE\"\n        v.vmx[\"mks.forceDiscreteGPU\"] = \"TRUE\"\n        v.vmx[\"gui.fullscreenatpoweron\"] = \"TRUE\"\n        v.vmx[\"gui.viewmodeatpoweron\"] = \"fullscreen\"\n        v.vmx[\"gui.lastPoweredViewMode\"] = \"fullscreen\"\n        v.vmx[\"sound.startconnected\"] = \"FALSE\"\n        v.vmx[\"sound.present\"] = \"FALSE\"\n        v.vmx[\"sound.autodetect\"] = \"TRUE\"\n        v.vmx[\"virtualhw.version\"] = \"14\"\n        v.enable_vmrun_ip_lookup = false\n        v.whitelist_verified = true\n        v.vmx[\"hgfs.linkRootShare\"] = \"FALSE\"\n    end\n\n    config.vm.provider :vmware_workstation do |v, override|\n        #v.gui = true\n        v.vmx[\"memsize\"] = \"2048\"\n        v.vmx[\"numvcpus\"] = \"2\"\n        v.vmx[\"ethernet0.virtualDev\"] = \"vmxnet3\"\n        v.vmx[\"RemoteDisplay.vnc.enabled\"] = \"false\"\n        v.vmx[\"RemoteDisplay.vnc.port\"] = \"5900\"\n        v.vmx[\"scsi0.virtualDev\"] = \"lsisas1068\"\n        v.enable_vmrun_ip_lookup = false\n        v.whitelist_verified = true\n        v.vmx[\"hgfs.linkRootShare\"] = \"FALSE\"\n    end\n    \n    config.vm.provider :libvirt do |libvirt, override|\n        libvirt.memory = 2048\n        libvirt.cpus = 2\n\n        # Use WinRM for the default synced folder; or disable it if\n        # WinRM is not available. Linux hosts don't support SMB,\n        # and Windows guests don't support NFS/9P/rsync\n        # See https://github.com/Cimpress-MCP/vagrant-winrm-syncedfolders\n        if Vagrant.has_plugin?(\"vagrant-winrm-syncedfolders\")\n            override.vm.synced_folder \".\", \"/vagrant\", type: \"winrm\"\n        else\n            override.vm.synced_folder \".\", \"/vagrant\", disabled: true\n        end\n\n        # Enable Hyper-V enlightments, see\n        # https://blog.wikichoon.com/2014/07/enabling-hyper-v-enlightenments-with-kvm.html\n        libvirt.hyperv_feature :name => 'stimer',  :state => 'on'\n        libvirt.hyperv_feature :name => 'relaxed', :state => 'on'\n        libvirt.hyperv_feature :name => 'vapic',   :state => 'on'\n        libvirt.hyperv_feature :name => 'synic',   :state => 'on'\n    end\nend\n"
  },
  {
    "path": "packer/vagrant/windows_10.json",
    "content": "{\n  \"builders\": [\n    {\n      \"boot_command\": \"\",\n      \"boot_wait\": \"6m\",\n      \"communicator\": \"winrm\",\n      \"cpus\": 2,\n      \"disk_adapter_type\": \"lsisas1068\",\n      \"disk_size\": \"{{user `disk_size`}}\",\n      \"disk_type_id\": \"{{user `disk_type_id`}}\",\n      \"floppy_files\": [\n        \"{{user `autounattend`}}\",\n        \"./scripts/fixnetwork.ps1\",\n        \"./scripts/disable-screensaver.ps1\",\n        \"./scripts/disable-winrm.ps1\",\n        \"./scripts/enable-winrm.ps1\",\n        \"./scripts/microsoft-updates.bat\",\n        \"./scripts/win-updates.ps1\"\n      ],\n      \"guest_os_type\": \"windows9-64\",\n      \"headless\": \"{{user `headless`}}\",\n      \"iso_checksum\": \"{{user `iso_checksum`}}\",\n      \"iso_url\": \"{{user `iso_url`}}\",\n      \"memory\": \"{{user `memory`}}\",\n      \"shutdown_command\": \"shutdown /s /t 10 /f /d p:4:1 /c \\\"Packer Shutdown\\\"\",\n      \"type\": \"vmware-iso\",\n      \"version\": \"{{user `vmx_version`}}\",\n      \"vm_name\": \"{{user `vm_name`}}\",\n      \"vmx_data\": {\n        \"RemoteDisplay.vnc.enabled\": \"false\",\n        \"RemoteDisplay.vnc.port\": \"5900\"\n      },\n      \"vmx_remove_ethernet_interfaces\": true,\n      \"vnc_port_max\": 5980,\n      \"vnc_port_min\": 5900,\n      \"winrm_password\": \"vagrant\",\n      \"winrm_timeout\": \"{{user `winrm_timeout`}}\",\n      \"winrm_username\": \"vagrant\"\n    },\n    {\n      \"boot_command\": \"\",\n      \"boot_wait\": \"6m\",\n      \"communicator\": \"winrm\",\n      \"cpus\": 2,\n      \"disk_size\": \"{{user `disk_size`}}\",\n      \"floppy_files\": [\n        \"{{user `autounattend`}}\",\n        \"./scripts/fixnetwork.ps1\",\n        \"./scripts/disable-screensaver.ps1\",\n        \"./scripts/disable-winrm.ps1\",\n        \"./scripts/enable-winrm.ps1\",\n        \"./scripts/microsoft-updates.bat\",\n        \"./scripts/win-updates.ps1\"\n      ],\n      \"guest_additions_mode\": \"disable\",\n      \"guest_os_type\": \"Windows10_64\",\n      \"headless\": \"{{user `headless`}}\",\n      \"iso_checksum\": \"{{user `iso_checksum`}}\",\n      \"iso_url\": \"{{user `iso_url`}}\",\n      \"memory\": \"{{user `memory`}}\",\n      \"shutdown_command\": \"shutdown /s /t 10 /f /d p:4:1 /c \\\"Packer Shutdown\\\"\",\n      \"type\": \"virtualbox-iso\",\n      \"vm_name\": \"{{user `vm_name`}}\",\n      \"winrm_password\": \"vagrant\",\n      \"winrm_timeout\": \"{{user `winrm_timeout`}}\",\n      \"winrm_username\": \"vagrant\"\n    }\n  ],\n  \"post-processors\": [\n    {\n      \"keep_input_artifact\": false,\n      \"output\": \"windows_10_{{.Provider}}.box\",\n      \"type\": \"vagrant\",\n      \"vagrantfile_template\": \"vagrantfile-windows_10.template\"\n    }\n  ],\n  \"provisioners\": [\n    {\n      \"execute_command\": \"{{ .Vars }} cmd /c \\\"{{ .Path }}\\\"\",\n      \"remote_path\": \"/tmp/script.bat\",\n      \"scripts\": [\n        \"./scripts/enable-rdp.bat\"\n      ],\n      \"type\": \"windows-shell\"\n    },\n    {\n      \"scripts\": [\n        \"./scripts/vm-guest-tools.ps1\"\n      ],\n      \"type\": \"powershell\"\n    },\n    {\n      \"restart_timeout\": \"{{user `restart_timeout`}}\",\n      \"type\": \"windows-restart\"\n    },\n    {\n      \"scripts\": [\n        \"./scripts/set-powerplan.ps1\"\n      ],\n      \"type\": \"powershell\"\n    },\n    {\n      \"execute_command\": \"{{ .Vars }} cmd /c \\\"{{ .Path }}\\\"\",\n      \"remote_path\": \"/tmp/script.bat\",\n      \"scripts\": [\n        \"./scripts/set-winrm-automatic.bat\",\n        \"./scripts/uac-enable.bat\",\n        \"./scripts/compile-dotnet-assemblies.bat\",\n        \"./scripts/dis-updates.bat\"\n      ],\n      \"type\": \"windows-shell\"\n    }\n  ],\n  \"variables\": {\n    \"autounattend\": \"./answer_files/10/Autounattend.xml\",\n    \"disk_size\": \"61440\",\n    \"disk_type_id\": \"1\",\n    \"memory\": \"2048\",\n    \"headless\": \"false\",\n    \"iso_checksum\": \"sha256:ef7312733a9f5d7d51cfa04ac497671995674ca5e1058d5164d6028f0938d668\",\n    \"iso_url\": \"https://software-static.download.prss.microsoft.com/dbazure/988969d5-f34g-4e03-ac9d-1f9786c66750/19045.2006.220908-0225.22h2_release_svc_refresh_CLIENTENTERPRISEEVAL_OEMRET_x64FRE_en-us.iso\",\n    \"restart_timeout\": \"5m\",\n    \"vhv_enable\": \"false\",\n    \"virtio_win_iso\": \"~/virtio-win.iso\",\n    \"vm_name\": \"windows_10\",\n    \"winrm_timeout\": \"6h\",\n    \"vmx_version\": \"14\"\n  }\n}\n"
  },
  {
    "path": "packer/vagrant/windows_11.json",
    "content": "{\n  \"builders\": [\n    {\n      \"boot_command\": [\n        \"<leftShiftOn><f10><leftShiftOff><wait>\",\n        \"reg add HKLM\\\\SYSTEM\\\\Setup\\\\LabConfig /t REG_DWORD /v BypassTPMCheck /d 1<return>\",\n        \"reg add HKLM\\\\SYSTEM\\\\Setup\\\\LabConfig /t REG_DWORD /v BypassSecureBootCheck /d 1<return><wait>\",\n        \"exit<return>\",\n        \"<wait><return>\"\n      ],\n      \"boot_wait\": \"2m\",\n      \"communicator\": \"winrm\",\n      \"cpus\": 2,\n      \"disk_adapter_type\": \"lsisas1068\",\n      \"disk_size\": \"{{user `disk_size`}}\",\n      \"disk_type_id\": \"{{user `disk_type_id`}}\",\n      \"floppy_files\": [\n        \"{{user `autounattend`}}\",\n        \"./scripts/fixnetwork.ps1\",\n        \"./scripts/disable-screensaver.ps1\",\n        \"./scripts/disable-winrm.ps1\",\n        \"./scripts/enable-winrm.ps1\",\n        \"./scripts/microsoft-updates.bat\",\n        \"./scripts/win-updates.ps1\"\n      ],\n      \"guest_os_type\": \"windows9-64\",\n      \"headless\": \"{{user `headless`}}\",\n      \"iso_checksum\": \"{{user `iso_checksum`}}\",\n      \"iso_url\": \"{{user `iso_url`}}\",\n      \"memory\": \"{{user `memory`}}\",\n      \"shutdown_command\": \"shutdown /s /t 10 /f /d p:4:1 /c \\\"Packer Shutdown\\\"\",\n      \"type\": \"vmware-iso\",\n      \"version\": \"{{user `vmx_version`}}\",\n      \"vm_name\": \"{{user `vm_name`}}\",\n      \"vmx_data\": {\n        \"RemoteDisplay.vnc.enabled\": \"false\",\n        \"RemoteDisplay.vnc.port\": \"5900\"\n      },\n      \"vmx_remove_ethernet_interfaces\": true,\n      \"vnc_port_max\": 5980,\n      \"vnc_port_min\": 5900,\n      \"winrm_password\": \"vagrant\",\n      \"winrm_timeout\": \"{{user `winrm_timeout`}}\",\n      \"winrm_username\": \"vagrant\"\n    },\n    {\n      \"boot_command\": [\n        \"<leftShiftOn><f10><leftShiftOff><wait>\",\n        \"reg add HKLM\\\\SYSTEM\\\\Setup\\\\LabConfig /t REG_DWORD /v BypassTPMCheck /d 1<return>\",\n        \"reg add HKLM\\\\SYSTEM\\\\Setup\\\\LabConfig /t REG_DWORD /v BypassSecureBootCheck /d 1<return><wait>\",\n        \"exit<return>\",\n        \"<wait><return>\"\n      ],\n      \"boot_wait\": \"2m\",\n      \"communicator\": \"winrm\",\n      \"cpus\": 2,\n      \"disk_size\": \"{{user `disk_size`}}\",\n      \"floppy_files\": [\n        \"{{user `autounattend`}}\",\n        \"./scripts/fixnetwork.ps1\",\n        \"./scripts/disable-screensaver.ps1\",\n        \"./scripts/disable-winrm.ps1\",\n        \"./scripts/enable-winrm.ps1\",\n        \"./scripts/microsoft-updates.bat\",\n        \"./scripts/win-updates.ps1\"\n      ],\n      \"guest_additions_mode\": \"disable\",\n      \"guest_os_type\": \"Windows10_64\",\n      \"headless\": \"{{user `headless`}}\",\n      \"iso_checksum\": \"{{user `iso_checksum`}}\",\n      \"iso_url\": \"{{user `iso_url`}}\",\n      \"memory\": \"{{user `memory`}}\",\n      \"shutdown_command\": \"shutdown /s /t 10 /f /d p:4:1 /c \\\"Packer Shutdown\\\"\",\n      \"type\": \"virtualbox-iso\",\n      \"vm_name\": \"{{user `vm_name`}}\",\n      \"winrm_password\": \"vagrant\",\n      \"winrm_timeout\": \"{{user `winrm_timeout`}}\",\n      \"winrm_username\": \"vagrant\"\n    }\n  ],\n  \"post-processors\": [\n    {\n      \"keep_input_artifact\": false,\n      \"output\": \"windows_11_{{.Provider}}.box\",\n      \"type\": \"vagrant\",\n      \"vagrantfile_template\": \"vagrantfile-windows_10.template\"\n    }\n  ],\n  \"provisioners\": [\n    {\n      \"execute_command\": \"{{ .Vars }} cmd /c \\\"{{ .Path }}\\\"\",\n      \"remote_path\": \"/tmp/script.bat\",\n      \"scripts\": [\n        \"./scripts/enable-rdp.bat\"\n      ],\n      \"type\": \"windows-shell\"\n    },\n    {\n      \"scripts\": [\n        \"./scripts/vm-guest-tools.ps1\"\n      ],\n      \"type\": \"powershell\"\n    },\n    {\n      \"restart_timeout\": \"{{user `restart_timeout`}}\",\n      \"type\": \"windows-restart\"\n    },\n    {\n      \"scripts\": [\n        \"./scripts/set-powerplan.ps1\"\n      ],\n      \"type\": \"powershell\"\n    },\n    {\n      \"execute_command\": \"{{ .Vars }} cmd /c \\\"{{ .Path }}\\\"\",\n      \"remote_path\": \"/tmp/script.bat\",\n      \"scripts\": [\n        \"./scripts/set-winrm-automatic.bat\",\n        \"./scripts/uac-enable.bat\",\n        \"./scripts/compile-dotnet-assemblies.bat\",\n        \"./scripts/dis-updates.bat\"\n      ],\n      \"type\": \"windows-shell\"\n    }\n  ],\n  \"variables\": {\n    \"autounattend\": \"./answer_files/11/Autounattend.xml\",\n    \"disk_size\": \"61440\",\n    \"disk_type_id\": \"1\",\n    \"memory\": \"4096\",\n    \"headless\": \"false\",\n    \"iso_checksum\": \"sha256:ebbc79106715f44f5020f77bd90721b17c5a877cbc15a3535b99155493a1bb3f\",\n    \"iso_url\": \"https://software-static.download.prss.microsoft.com/dbazure/988969d5-f34g-4e03-ac9d-1f9786c66751/22621.525.220925-0207.ni_release_svc_refresh_CLIENTENTERPRISEEVAL_OEMRET_x64FRE_en-us.iso\",\n    \"restart_timeout\": \"5m\",\n    \"vhv_enable\": \"false\",\n    \"virtio_win_iso\": \"~/virtio-win.iso\",\n    \"vm_name\": \"windows_11\",\n    \"winrm_timeout\": \"6h\",\n    \"vmx_version\": \"14\"\n  }\n}\n"
  },
  {
    "path": "packer/vagrant/windows_2019.json",
    "content": "{\n  \"builders\": [\n    {\n      \"boot_wait\": \"2m\",\n      \"communicator\": \"winrm\",\n      \"cpus\": 2,\n      \"disk_adapter_type\": \"lsisas1068\",\n      \"disk_size\": \"{{user `disk_size`}}\",\n      \"disk_type_id\": \"{{user `disk_type_id`}}\",\n      \"floppy_files\": [\n        \"{{user `autounattend`}}\",\n        \"./scripts/disable-screensaver.ps1\",\n        \"./scripts/disable-winrm.ps1\",\n        \"./scripts/enable-winrm.ps1\",\n        \"./scripts/microsoft-updates.bat\",\n        \"./scripts/unattend.xml\",\n        \"./scripts/sysprep.bat\",\n        \"./scripts/win-updates.ps1\"\n      ],\n      \"guest_os_type\": \"windows9srv-64\",\n      \"headless\": \"{{user `headless`}}\",\n      \"iso_checksum\": \"{{user `iso_checksum`}}\",\n      \"iso_url\": \"{{user `iso_url`}}\",\n      \"memory\": \"{{user `memory`}}\",\n      \"shutdown_command\": \"a:/sysprep.bat\",\n      \"type\": \"vmware-iso\",\n      \"version\": \"{{user `vmx_version`}}\",\n      \"vm_name\": \"WindowsServer2019\",\n      \"vmx_data\": {\n        \"RemoteDisplay.vnc.enabled\": \"false\",\n        \"RemoteDisplay.vnc.port\": \"5900\"\n      },\n      \"vmx_remove_ethernet_interfaces\": true,\n      \"vnc_port_max\": 5980,\n      \"vnc_port_min\": 5900,\n      \"winrm_password\": \"vagrant\",\n      \"winrm_timeout\": \"{{user `winrm_timeout`}}\",\n      \"winrm_username\": \"vagrant\"\n    },\n    {\n      \"boot_wait\": \"2m\",\n      \"communicator\": \"winrm\",\n      \"cpus\": 2,\n      \"disk_size\": \"{{user `disk_size`}}\",\n      \"floppy_files\": [\n        \"{{user `autounattend`}}\",\n        \"./scripts/disable-screensaver.ps1\",\n        \"./scripts/disable-winrm.ps1\",\n        \"./scripts/enable-winrm.ps1\",\n        \"./scripts/microsoft-updates.bat\",\n        \"./scripts/win-updates.ps1\",\n        \"./scripts/unattend.xml\",\n        \"./scripts/sysprep.bat\"\n      ],\n      \"guest_additions_mode\": \"disable\",\n      \"guest_os_type\": \"Windows2016_64\",\n      \"headless\": \"{{user `headless`}}\",\n      \"iso_checksum\": \"{{user `iso_checksum`}}\",\n      \"iso_url\": \"{{user `iso_url`}}\",\n      \"memory\": \"{{user `memory`}}\",\n      \"shutdown_command\": \"a:/sysprep.bat\",\n      \"type\": \"virtualbox-iso\",\n      \"vm_name\": \"WindowsServer2019\",\n      \"winrm_password\": \"vagrant\",\n      \"winrm_timeout\": \"{{user `winrm_timeout`}}\",\n      \"winrm_username\": \"vagrant\"\n    }\n  ],\n  \"post-processors\": [\n    {\n      \"keep_input_artifact\": false,\n      \"output\": \"windows_2019_{{.Provider}}.box\",\n      \"type\": \"vagrant\",\n      \"vagrantfile_template\": \"vagrantfile-windows_2016.template\"\n    }\n  ],\n  \"provisioners\": [\n    {\n      \"execute_command\": \"{{ .Vars }} cmd /c \\\"{{ .Path }}\\\"\",\n      \"scripts\": [\n        \"./scripts/enable-rdp.bat\"\n      ],\n      \"type\": \"windows-shell\"\n    },\n    {\n      \"scripts\": [\n        \"./scripts/vm-guest-tools.ps1\"\n      ],\n      \"type\": \"powershell\"\n    },\n    {\n      \"restart_timeout\": \"{{user `restart_timeout`}}\",\n      \"type\": \"windows-restart\"\n    },\n    {\n      \"execute_command\": \"{{ .Vars }} cmd /c \\\"{{ .Path }}\\\"\",\n      \"scripts\": [\n        \"./scripts/set-winrm-automatic.bat\",\n        \"./scripts/uac-enable.bat\",\n        \"./scripts/compile-dotnet-assemblies.bat\",\n        \"./scripts/dis-updates.bat\"\n      ],\n      \"type\": \"windows-shell\"\n    }\n  ],\n  \"variables\": {\n    \"autounattend\": \"./answer_files/2019/Autounattend.xml\",\n    \"disk_size\": \"61440\",\n    \"disk_type_id\": \"1\",\n    \"memory\": \"2048\",\n    \"headless\": \"false\",\n    \"hyperv_switchname\": \"{{env `hyperv_switchname`}}\",\n    \"iso_checksum\": \"sha256:6dae072e7f78f4ccab74a45341de0d6e2d45c39be25f1f5920a2ab4f51d7bcbb\",\n    \"iso_url\": \"https://software-static.download.prss.microsoft.com/dbazure/988969d5-f34g-4e03-ac9d-1f9786c66749/17763.3650.221105-1748.rs5_release_svc_refresh_SERVER_EVAL_x64FRE_en-us.iso\",\n    \"manually_download_iso_from\": \"https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2019\",\n    \"restart_timeout\": \"5m\",\n    \"virtio_win_iso\": \"~/virtio-win.iso\",\n    \"winrm_timeout\": \"2h\",\n    \"vmx_version\": \"14\"\n  }\n}\n"
  },
  {
    "path": "packer/vagrant/windows_2022.json",
    "content": "{\n  \"builders\": [\n    {\n      \"boot_wait\": \"2m\",\n      \"communicator\": \"winrm\",\n      \"cpus\": 2,\n      \"disk_adapter_type\": \"lsisas1068\",\n      \"disk_size\": \"{{user `disk_size`}}\",\n      \"disk_type_id\": \"{{user `disk_type_id`}}\",\n      \"floppy_files\": [\n        \"{{user `autounattend`}}\",\n        \"./scripts/disable-screensaver.ps1\",\n        \"./scripts/disable-winrm.ps1\",\n        \"./scripts/enable-winrm.ps1\",\n        \"./scripts/microsoft-updates.bat\",\n        \"./scripts/win-updates.ps1\",\n        \"./scripts/unattend.xml\",\n        \"./scripts/sysprep.bat\"\n      ],\n      \"guest_os_type\": \"windows9srv-64\",\n      \"headless\": \"{{user `headless`}}\",\n      \"iso_checksum\": \"{{user `iso_checksum`}}\",\n      \"iso_url\": \"{{user `iso_url`}}\",\n      \"memory\": \"{{user `memory`}}\",\n      \"shutdown_command\": \"a:/sysprep.bat\",\n      \"type\": \"vmware-iso\",\n      \"version\": \"{{user `vmx_version`}}\",\n      \"vm_name\": \"WindowsServer2022\",\n      \"vmx_data\": {\n        \"RemoteDisplay.vnc.enabled\": \"false\",\n        \"RemoteDisplay.vnc.port\": \"5900\"\n      },\n      \"vmx_remove_ethernet_interfaces\": true,\n      \"vnc_port_max\": 5980,\n      \"vnc_port_min\": 5900,\n      \"winrm_password\": \"vagrant\",\n      \"winrm_timeout\": \"{{user `winrm_timeout`}}\",\n      \"winrm_username\": \"vagrant\"\n    },\n    {\n      \"boot_wait\": \"2m\",\n      \"communicator\": \"winrm\",\n      \"cpus\": 2,\n      \"disk_size\": \"{{user `disk_size`}}\",\n      \"floppy_files\": [\n        \"{{user `autounattend`}}\",\n        \"./scripts/disable-screensaver.ps1\",\n        \"./scripts/disable-winrm.ps1\",\n        \"./scripts/enable-winrm.ps1\",\n        \"./scripts/microsoft-updates.bat\",\n        \"./scripts/win-updates.ps1\",\n        \"./scripts/unattend.xml\",\n        \"./scripts/sysprep.bat\"\n      ],\n      \"guest_additions_mode\": \"disable\",\n      \"guest_os_type\": \"Windows2016_64\",\n      \"headless\": \"{{user `headless`}}\",\n      \"iso_checksum\": \"{{user `iso_checksum`}}\",\n      \"iso_url\": \"{{user `iso_url`}}\",\n      \"memory\": \"{{user `memory`}}\",\n      \"shutdown_command\": \"a:/sysprep.bat\",\n      \"type\": \"virtualbox-iso\",\n      \"vm_name\": \"WindowsServer2022\",\n      \"winrm_password\": \"vagrant\",\n      \"winrm_timeout\": \"{{user `winrm_timeout`}}\",\n      \"winrm_username\": \"vagrant\"\n    }\n  ],\n  \"post-processors\": [\n    {\n      \"keep_input_artifact\": false,\n      \"output\": \"windows_2022_{{.Provider}}.box\",\n      \"type\": \"vagrant\",\n      \"vagrantfile_template\": \"vagrantfile-windows_2016.template\"\n    }\n  ],\n  \"provisioners\": [\n    {\n      \"execute_command\": \"{{ .Vars }} cmd /c \\\"{{ .Path }}\\\"\",\n      \"scripts\": [\n        \"./scripts/enable-rdp.bat\"\n      ],\n      \"type\": \"windows-shell\"\n    },\n    {\n      \"scripts\": [\n        \"./scripts/vm-guest-tools.ps1\"\n      ],\n      \"type\": \"powershell\"\n    },\n    {\n      \"restart_timeout\": \"{{user `restart_timeout`}}\",\n      \"type\": \"windows-restart\"\n    },\n    {\n      \"execute_command\": \"{{ .Vars }} cmd /c \\\"{{ .Path }}\\\"\",\n      \"scripts\": [\n        \"./scripts/set-winrm-automatic.bat\",\n        \"./scripts/uac-enable.bat\",\n        \"./scripts/compile-dotnet-assemblies.bat\",\n        \"./scripts/dis-updates.bat\"\n      ],\n      \"type\": \"windows-shell\"\n    }\n  ],\n  \"variables\": {\n    \"autounattend\": \"./answer_files/2022/Autounattend.xml\",\n    \"disk_size\": \"61440\",\n    \"disk_type_id\": \"1\",\n    \"memory\": \"2048\",\n    \"headless\": \"false\",\n    \"hyperv_switchname\": \"{{env `hyperv_switchname`}}\",\n    \"iso_checksum\": \"sha256:3e4fa6d8507b554856fc9ca6079cc402df11a8b79344871669f0251535255325\",\n    \"iso_url\": \"https://software-static.download.prss.microsoft.com/sg/download/888969d5-f34g-4e03-ac9d-1f9786c66749/SERVER_EVAL_x64FRE_en-us.iso\",\n    \"manually_download_iso_from\": \"https://www.microsoft.com/en-us/evalcenter/evaluate-windows-server-2022\",\n    \"restart_timeout\": \"5m\",\n    \"virtio_win_iso\": \"~/virtio-win.iso\",\n    \"winrm_timeout\": \"2h\",\n    \"vmx_version\": \"14\"\n  }\n}\n\n"
  },
  {
    "path": "playbooks.yml",
    "content": "NHA:\n  - build.yml\n  - ad-servers.yml\n  - ad-parent_domain.yml\n  # - ad-child_domain.yml\n  - ad-members.yml\n  - ad-trusts.yml\n  - ad-data.yml\n  - ad-gmsa.yml\n  # - laps.yml\n  - ad-relations.yml\n  - adcs.yml\n  - ad-acl.yml\n  - servers.yml\n  - security.yml\n  - vulnerabilities.yml\n\nSCCM:\n  - build.yml\n  - ad-servers.yml\n  - ad-parent_domain.yml\n  # - ad-child_domain.yml\n  - ad-members.yml\n  # - ad-trusts.yml\n  - ad-data.yml\n  # - ad-gmsa.yml\n  # - laps.yml\n  - ad-relations.yml\n  # - adcs.yml\n  - ad-acl.yml\n  - servers.yml\n  - security.yml\n  - vulnerabilities.yml\n  - sccm-install.yml\n  # Waiting 10 minutes for the install to complete\n  - wait5m.yml\n  - wait5m.yml\n  - reboot.yml\n  # reboot before launching the sccm config to finish the install\n  # Waiting 5 minutes before launching the configuration\n  - wait5m.yml\n  - dhcp.yml\n  - sccm-config.yml\n  - sccm-pxe.yml\n  # replay client install fix some issue in enrollment for CLIENT\n  - sccm-client.yml\n\nGOAD-Mini:\n  - build.yml\n  - ad-servers.yml\n  - ad-parent_domain.yml\n  - ad-data.yml\n  - ad-relations.yml\n  - adcs.yml\n  - ad-acl.yml\n  - security.yml\n  - vulnerabilities.yml\n\nDRACARYS:\n  - build.yml\n  - ad-servers.yml\n  - ad-parent_domain.yml\n  - ad-members.yml\n  - ad-enroll_linux.yml\n  - ad-data.yml\n  - ad-relations.yml\n  - ad-acl.yml\n  - klink.yml\n  - keepass.yml\n  - security.yml\n  - vulnerabilities.yml\n  - reboot.yml\n  - glpi.yml\n\ndefault:\n  - build.yml\n  - ad-servers.yml\n  - ad-parent_domain.yml\n  # Wait after the child domain creation before adding servers\n  - ad-child_domain.yml\n  # Waiting 5 minutes for the child domain to be ready\n  - wait5m.yml\n  - ad-members.yml\n  - ad-trusts.yml\n  - ad-data.yml\n  - ad-gmsa.yml\n  - laps.yml\n  - ad-relations.yml\n  - adcs.yml\n  - ad-acl.yml\n  - servers.yml\n  - security.yml\n  - vulnerabilities.yml"
  },
  {
    "path": "pyproject.toml",
    "content": "[tool.poetry]\nname = \"goad\"\nversion = \"3.0.0\"\ndescription = \"Game of active directory, an active directory lab project\"\nauthors = [\"Mayfly277 <mayfly277@gmail.com>\"]\nlicense = \"GPL-3.0-or-later\"\nreadme = \"README.md\"\n\n[tool.poetry.dependencies]\npython = \"^3.8\"\nrich = \"^13.9.4\"\npsutil = \"^6.1.0\"\nJinja2 = \"^3.1.4\"\nPyYAML = \"^6.0.2\"\nsetuptools = {version = \"^75.6.0\", python = \">=3.9\"}\nansible-runner = [{ version = \"==2.3.6\", python = \"==3.8\" },\n                  { version = \"^2.4.0\", python = \">=3.9\" }]\nansible-core = [{ version = \"==2.12.6\", python = \"<3.11\" },\n                { version = \"==2.18.0\", python = \">=3.11\" }]\npywinrm = \"^0.5.0\"\nazure-identity = \"^1.19.0\"\nazure-mgmt-compute = \"^33.0.0\"\nazure-mgmt-network = \"^28.0.0\"\nboto3 = \"^1.35.70\"\nproxmoxer = \"^2.1.0\"\nrequests = \"^2.32.3\"\n\n\n[build-system]\nrequires = [\"poetry-core\"]\nbuild-backend = \"poetry.core.masonry.api\"\n"
  },
  {
    "path": "requirements.yml",
    "content": "rich\npsutil\nJinja2\npyyaml\n# Ansible\nansible_runner\n# ansible-core 2.12.6 min version python 3.8\nansible-core==2.12.6\npywinrm\n# AZURE\nazure-identity\nazure-mgmt-compute\nazure-mgmt-network\n# AWS\nboto3\n# Proxmox\nproxmoxer\nrequests"
  },
  {
    "path": "requirements_311.yml",
    "content": "rich\npsutil\nJinja2\npyyaml\n# Ansible\n# setuptools for python >= 3.12\nsetuptools\nansible_runner\n# fix ansible-core version to avoid breaking changes\n# ansible-core 2.18.0 min version python 3.11\nansible-core==2.18.0\npywinrm\n# AZURE\nazure-identity\nazure-mgmt-compute\nazure-mgmt-network\n# AWS\nboto3\n# Proxmox\nproxmoxer\nrequests"
  },
  {
    "path": "scripts/check.sh",
    "content": "#!/usr/bin/env bash\n\n# This source code come from the opensource project DetectionLab : https://github.com/clong/DetectionLab\n# This script is meant to verify that your system is configured to build the lab successfully.\n\nERROR=$(tput setaf 1; echo -n \"  [!]\"; tput sgr0)\nGOODTOGO=$(tput setaf 2; echo -n \"  [✓]\"; tput sgr0)\nINFO=$(tput setaf 3; echo -n \"  [-]\"; tput sgr0)\n\nPROVIDERS=\"virtualbox vmware azure proxmox vmware_esxi\"\nANSIBLE_HOSTS=\"docker local\"\nprint_usage() {\n  echo \"Usage: ./check.sh <provider> <ansible_host>\"\n  echo \"provider must be one of the following:\"\n  for p in $PROVIDERS;  do\n    echo \" - $p\";\n  done\n  echo \"Ansible host must be one of the following:\"\n  for a in $ANSIBLE_HOSTS;  do\n    echo \" - $a\";\n  done\n  exit 0\n}\n\nif [ $# -lt 2 ]; then\n  print_usage\nelse\n  PROVIDER=$1\n  ANSIBLE_HOST=$2\nfi\n\ncheck_vagrant_path() {\n  if ! which vagrant >/dev/null; then\n    (echo >&2 \"${ERROR} Vagrant was not found in your PATH.\")\n    (echo >&2 \"${ERROR} Please correct this before continuing. Exiting.\")\n    (echo >&2 \"${ERROR} Correct this by installing Vagrant : https://www.vagrantup.com/downloads.html\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} Vagrant was found in your PATH\")\n\n    # Ensure Vagrant >= 2.2.9\n    # https://unix.stackexchange.com/a/285928\n    VAGRANT_VERSION=\"$(vagrant --version | cut -d ' ' -f 2)\"\n    REQUIRED_VERSION=\"2.2.9\"\n    # If the version of Vagrant is not greater or equal to the required version\n    if ! [ \"$(printf '%s\\n' \"$REQUIRED_VERSION\" \"$VAGRANT_VERSION\" | sort -V | head -n1)\" = \"$REQUIRED_VERSION\" ]; then\n        (echo >&2 \"${ERROR} WARNING: It is highly recommended to use Vagrant $REQUIRED_VERSION or above before continuing\")\n    else \n        (echo >&2 \"${GOODTOGO} Your version of Vagrant ($VAGRANT_VERSION) is supported\")\n    fi\n  fi\n}\n\ncheck_packer_path() {\n  if ! which packer >/dev/null; then\n    (echo >&2 \"${ERROR} packer was not found in your PATH.\")\n    (echo >&2 \"${ERROR} Please correct this before continuing. Exiting.\")\n    (echo >&2 \"${ERROR} Correct this by installing packer : https://developer.hashicorp.com/packer/docs/install\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} packer was found in your PATH\")\n  fi\n}\n\ncheck_terraform_path() {\n  if ! which terraform >/dev/null; then\n    (echo >&2 \"${ERROR} terraform was not found in your PATH.\")\n    (echo >&2 \"${ERROR} Please correct this before continuing. Exiting.\")\n    (echo >&2 \"${ERROR} Correct this by installing terraform : https://developer.hashicorp.com/terraform/downloads\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} terraform was found in your PATH\")\n  fi\n}\n\ncheck_sshpass_path() {\n  if ! which sshpass >/dev/null; then\n    (echo >&2 \"${ERROR} sshpass was not found in your PATH.\")\n    (echo >&2 \"${ERROR} Please correct this before continuing. Exiting.\")\n    (echo >&2 \"${ERROR} Correct this by installing sshpass\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} sshpass was found in your PATH\")\n  fi\n}\n\n# Returns 0 if not installed or 1 if installed\ncheck_virtualbox_installed() {\n  if ! which VBoxManage >/dev/null; then\n    (echo >&2 \"${ERROR} VBoxManage was not found in your PATH.\")\n    (echo >&2 \"${ERROR} Please correct this before continuing. Exiting.\")\n    (echo >&2 \"${ERROR} Correct this by installing virtualbox\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} virtualbox is installed\")\n  fi\n}\n\ncheck_aws_installed() {\n  if ! which aws >/dev/null; then\n    (echo >&2 \"${ERROR} aws was not found in your PATH.\")\n    (echo >&2 \"${ERROR} Please correct this before continuing. Exiting.\")\n    (echo >&2 \"${ERROR} Correct this by installing aws (https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} aws is installed\")\n  fi\n}\n\ncheck_azure_installed() {\n  if ! which az >/dev/null; then\n    (echo >&2 \"${ERROR} az was not found in your PATH.\")\n    (echo >&2 \"${ERROR} Please correct this before continuing. Exiting.\")\n    (echo >&2 \"${ERROR} Correct this by installing az (https://learn.microsoft.com/en-us/cli/azure/install-azure-cli)\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} azure is installed\")\n  fi\n}\n\ncheck_rsync_path() {\n  if ! which rsync >/dev/null; then\n    (echo >&2 \"${ERROR} rsync was not found in your PATH.\")\n    (echo >&2 \"${ERROR} Please correct this before continuing. Exiting.\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} rsync was found in your PATH\")\n  fi\n}\n\n# Returns 0 if not installed or 1 if installed\n# Check for VMWare Workstation on Linux\ncheck_vmware_workstation_installed() {\n  if ! which vmrun >/dev/null; then\n    (echo >&2 \"${ERROR} vmrun was not found in your PATH.\")\n    (echo >&2 \"${ERROR} Please correct this before continuing. Exiting.\")\n    (echo >&2 \"${ERROR} Correct this by installing vmware\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} vmware is installed\")\n  fi\n}\n\ncheck_docker_installed() {\n  if ! which docker >/dev/null; then\n    (echo >&2 \"${ERROR} docker was not found in your PATH.\")\n  else\n    (echo >&2 \"${GOODTOGO} docker is installed\")\n  fi\n}\n\ncheck_ansible_installed() {\n  if ! which ansible >/dev/null; then\n    (echo >&2 \"${ERROR} ansible was not found in your PATH.\")\n  else\n    (echo >&2 \"${GOODTOGO} ansible is installed\")\n  fi\n}\n\ncheck_python_env(){\n  if ! which python3 >/dev/null; then\n    (echo >&2 \"${ERROR} python3 was not found in your PATH.\")\n  else\n    (echo >&2 \"${GOODTOGO} python3 is installed\")\n    PYTHON_VERSION=$(python3 --version | cut -d ' ' -f 2)\n    REQUIRED_VERSION=\"3.8\"\n    if [ \"$(printf '%s\\n' \"$REQUIRED_VERSION\" \"$PYTHON_VERSION\" | sort -V | head -n1)\" = \"$REQUIRED_VERSION\" ]; then\n      (echo >&2 \"${GOODTOGO} python3 ($PYTHON_VERSION) is supported\")\n      check_ansible_env\n    else\n      (echo >&2 \"${ERROR} python3 ($PYTHON_VERSION) is not supported start checking other available python interpreter\")\n      check_python_venv\n      exit 1\n    fi\n  fi\n}\n\ncheck_python_venv(){\n    PYTHON_INSTALLED=$(ls -1 /usr/bin/python* | grep '.*[3]\\(.[0-9]\\+\\)\\?$')\n    REQUIRED_VERSION=\"3.8\"\n    GOOD_PYTHON=\"\"\n    (echo >&2 \"${GOODTOGO} Supported python3 interpreter :\")\n    for python_interpreter in $PYTHON_INSTALLED;  do\n      PYTHON_VERSION=\"$($python_interpreter --version | cut -d ' ' -f 2)\"\n      # If the version of python is not greater or equal to the required version\n      if [ \"$(printf '%s\\n' \"$REQUIRED_VERSION\" \"$PYTHON_VERSION\" | sort -V | head -n1)\" = \"$REQUIRED_VERSION\" ]; then\n          (echo >&2 \"  ${GOODTOGO} $python_interpreter ($PYTHON_VERSION) is supported\")\n          GOOD_PYTHON=$(echo \"$GOOD_PYTHON\" \"$python_interpreter\")\n      fi\n    done\n\n    INTERPRETER_FOUND=0\n    if [ \"$GOOD_PYTHON\" != \"\" ]; then\n      (echo >&2 \"${GOODTOGO} Verify python3 available environment :\")\n      for python in $GOOD_PYTHON; do\n        (echo >&2 \"${GOODTOGO} Checking $python :\")\n        VENV_FOUND=0\n        VIRTUALENV_FOUND=0\n        PIP_FOUND=0\n        if [ \"$($python -m venv -h 2>/dev/null | grep -i 'usage:')\" ]; then\n          (echo >&2 \"  ${GOODTOGO} $python venv module is installed\")\n          VENV_FOUND=1\n        else\n          (echo >&2 \"  ${ERROR} $python venv module not installed\")\n        fi\n\n        if [ \"$($python -m virtualenv -h 2>/dev/null | grep -i 'usage:')\" ]; then\n          (echo >&2 \"  ${GOODTOGO} $python virtualenv module is installed\")\n          VIRTUALENV_FOUND=1\n        else\n          (echo >&2 \"  ${ERROR} $python virtualenv module not installed\")\n        fi\n\n        if [ \"$($python -m pip -h 2>/dev/null | grep -i 'usage:')\" ]; then\n          (echo >&2 \"  ${GOODTOGO} $python pip module is installed\")\n          PIP_FOUND=1\n        else\n          (echo >&2 \"  ${ERROR} $python pip module not installed\")\n        fi\n\n        if [[ $PIP_FOUND -eq 1 ]] && [[ $VENV_FOUND -eq 1 || $VIRTUALENV_FOUND -eq 1 ]]; then\n          if [ \"$VIRTUALENV_FOUND\" -eq 1 ]; then\n            (echo >&2 \"  ${GOODTOGO} $python environment is available consider creating a venv : \\\"$python -m virtualenv .venv\\\", activate it with source .venv/bin/activate and relaunch the prepare script\")\n          else\n            (echo >&2 \"  ${GOODTOGO} $python environment is available consider creating a venv : \\\"$python -m venv .venv\\\", activate it with source .venv/bin/activate and relaunch the prepare script\")\n          fi\n          INTERPRETER_FOUND=1\n        fi\n      done\n    fi\n\n    if [ \"$INTERPRETER_FOUND\" -eq 1 ]; then\n      (echo >&2 \"  ${ERROR} no available interpreter found, please install pip and venv\")\n    fi\n}\n\ncheck_ansible_env(){\n  (echo >&2 \"${GOODTOGO} Checking if python3 env is ansible ready :\")\n  ANSIBLE_CORE_CHECK=$(python3 -m pip --disable-pip-version-check list|grep -c ansible-core)\n  if [ \"$ANSIBLE_CORE_CHECK\" -eq 1 ]; then\n    ANSIBLE_VERSION=$(python3 -m pip --disable-pip-version-check list|grep ansible-core|cut -d ' ' -f 2-|sed -e 's/ //g' )\n    REQUIRED_VERSION=\"2.12.6\"\n    if [ \"$(printf '%s\\n' \"$REQUIRED_VERSION\" \"$ANSIBLE_VERSION\" | sort -V | head -n1)\" = \"$REQUIRED_VERSION\" ]; then\n      (echo >&2 \"  ${GOODTOGO} ansible-core $ANSIBLE_VERSION  is supported\")\n    else\n      (echo >&2 \"  ${ERROR} $ANSIBLE_VERSION  is not supported consider doing :\")\n      echo \"        python3 -m pip install ansible-core==2.12.6\"\n    fi\n  else\n    (echo >&2 \"  ${ERROR} ansible-core is not installed consider doing :\")\n    echo \"        python3 -m pip install ansible-core==2.12.6\"\n  fi\n\n  PYWINRM_CHECK=$(python3 -m pip --disable-pip-version-check list |grep -c pywinrm )\n  if [ \"$PYWINRM_CHECK\" -eq 1 ]; then\n    (echo >&2 \"  ${GOODTOGO} pywinrm is installed\")\n  else\n    (echo >&2 \"  ${ERROR} pywinrm  is not install consider doing :\")\n    echo \"        python3 -m pip install pywinrm\"\n    exit 1\n  fi\n\n  if ! which ansible >/dev/null; then\n    (echo >&2 \"${ERROR} ansible was not found in your PATH abort\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} ansible is installed\")\n  fi\n\n  if ! which ansible-galaxy >/dev/null; then\n    (echo >&2 \"${ERROR} ansible-galaxy was not found in your PATH abort\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} ansible-galaxy is installed\")\n  fi\n\n  GALAXY_COLLECTION=$(ansible-galaxy collection list)\n  ANSIBLE_COLLECTION_EXPECTED=\"community.windows community.general ansible.windows\"\n  GALAXY_OK=1\n  for collection in $ANSIBLE_COLLECTION_EXPECTED; do\n    if [ $(echo $GALAXY_COLLECTION|grep -c $collection) -eq 1 ]; then\n      (echo >&2 \"  ${GOODTOGO} ansible-galaxy collection $collection installed\")\n    else\n      (echo >&2 \"  ${ERROR} ansible-galaxy collection $collection not installed\")\n      GALAXY_OK=0\n    fi\n  done\n  if [ $GALAXY_OK -eq 0 ]; then\n    (echo >&2 \"${ERROR} ansible-galaxy requirements missing consider doing : ansible-galaxy install -r ansible/requirements.yml\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} ansible-galaxy requirements ok\")\n  fi\n}\n\n# Returns 0 if not installed or 1 if installed\ncheck_vmware_desktop_vagrant_plugin_installed() {\n  LEGACY_PLUGIN_CHECK=\"$(vagrant plugin list | grep -c 'vagrant-vmware-fusion')\"\n  if [ \"$LEGACY_PLUGIN_CHECK\" -gt 0 ]; then\n    (echo >&2 \"${ERROR} The VMware Fusion Vagrant plugin is deprecated and is no longer supported.\")\n    (echo >&2 \"${INFO} Please upgrade to the VMware Desktop plugin: https://www.vagrantup.com/docs/vmware/installation.html\")\n    (echo >&2 \"${INFO} Please also uninstall the vagrant-vmware-fusion plugin and install the vmware-vagrant-desktop plugin\")\n    (echo >&2 \"${INFO} HINT: \\`vagrant plugin uninstall vagrant-vmware-fusion && vagrant plugin install vagrant-vmware-desktop\\`\")\n    (echo >&2 \"${INFO} NOTE: The VMware plugin does not work with trial versions of VMware Fusion\")\n    exit 1\n  fi\n\n  VMWARE_DESKTOP_PLUGIN_PRESENT=\"$(vagrant plugin list | grep -c 'vagrant-vmware-desktop')\"\n  if [ \"$VMWARE_DESKTOP_PLUGIN_PRESENT\" -eq 0 ]; then\n    (echo >&2 \"VMWare Fusion or Workstation is installed, but the vagrant-vmware-desktop plugin is not.\")\n    (echo >&2 \"Visit https://www.hashicorp.com/blog/introducing-the-vagrant-vmware-desktop-plugin for more information on how to purchase and install it\")\n    (echo >&2 \"VMWare Fusion or Workstation will not be listed as a provider until the vagrant-vmware-desktop plugin has been installed.\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} vagrant-vmware-desktop plugin installed\")\n  fi\n}\n\ncheck_vagrant_vmware_utility_installed() {\n  # Ensure the helper utility is installed: https://www.vagrantup.com/docs/providers/vmware/vagrant-vmware-utility\n  if ! pgrep -f vagrant-vmware-utility > /dev/null; then\n    (echo >&2 \"${ERROR} vagrant-vmware-utility is not installed (https://developer.hashicorp.com/vagrant/docs/providers/vmware/vagrant-vmware-utility)\")\n    exit 1\n  else\n    (echo >&2 \"${GOODTOGO} vagrant-vmware-utility installed\")\n  fi\n}\n\n# Check to see if any Vagrant instances exist already\ncheck_vagrant_instances_exist() {\n  cd \"$VAGRANT_DIR\"|| exit 1\n  # Vagrant status has the potential to return a non-zero error code, so we work around it with \"|| true\"\n  VAGRANT_STATUS_OUTPUT=$(vagrant status)\n  VAGRANT_BUILT=$(echo \"$VAGRANT_STATUS_OUTPUT\" | grep -c 'not created') || true\n  if [ \"$VAGRANT_BUILT\" -ne 4 ]; then\n    (echo >&2 \"${INFO} You appear to have already created at least one Vagrant instance:\")\n    # shellcheck disable=SC2164\n    cd \"$VAGRANT_DIR\" && echo \"$VAGRANT_STATUS_OUTPUT\" | grep -v 'not created' | grep -E 'logger|dc|wef|win10' \n    (echo >&2 \"${INFO} If you want to start with a fresh install, you should run \\`vagrant destroy -f\\` to remove existing instances.\")\n  else \n    (echo >&2 \"${GOODTOGO} No Vagrant instances have been created yet\")\n  fi\n}\n\ncheck_vagrant_reload_plugin() {\n  # Ensure the vagrant-reload plugin is installed\n  VAGRANT_RELOAD_PLUGIN_INSTALLED=$(vagrant plugin list | grep -c 'vagrant-reload')\n  if [ \"$VAGRANT_RELOAD_PLUGIN_INSTALLED\" != \"1\" ]; then\n    (echo >&2 \"${ERROR} The vagrant-reload plugin is required and was not found. This script will attempt to install it now.\")\n    if ! $(which vagrant) plugin install \"vagrant-reload\"; then\n      (echo >&2 \"Unable to install the vagrant-reload plugin. Please try to do so manually and re-run this script.\")\n      exit 1\n    else \n      (echo >&2 \"${GOODTOGO} The vagrant-reload plugin was successfully installed!\")\n    fi\n  else\n    (echo >&2 \"${GOODTOGO} The vagrant-reload plugin is currently installed\")\n  fi\n}\n\ncheck_vagrant_esxi_plugin() {\n  # Ensure the vagrant-vmware-esxi plugin is installed\n  VAGRANT_ESXI_PLUGIN_INSTALLED=$(vagrant plugin list | grep -c 'vagrant-vmware-esxi')\n  if [ \"$VAGRANT_ESXI_PLUGIN_INSTALLED\" != \"1\" ]; then\n    (echo >&2 \"${ERROR} The vagrant-vmware-esxi plugin is required and was not found. This script will attempt to install it now.\")\n    if ! $(which vagrant) plugin install \"vagrant-vmware-esxi\"; then\n      (echo >&2 \"Unable to install the vagrant-vmware-esxi plugin. Please try to do so manually and re-run this script.\")\n      exit 1\n    else \n      (echo >&2 \"${GOODTOGO} The vagrant-vmware-esxi plugin was successfully installed!\")\n    fi\n  else\n    (echo >&2 \"${GOODTOGO} The vagrant-vmware-esxi plugin is currently installed\")\n  fi\n}\n\ncheck_vagrant_env_plugin() {\n  # Ensure the vagrant-env plugin is installed\n  VAGRANT_ENV_PLUGIN_INSTALLED=$(vagrant plugin list | grep -c 'vagrant-env')\n  if [ \"$VAGRANT_ENV_PLUGIN_INSTALLED\" != \"1\" ]; then\n    (echo >&2 \"${ERROR} The vagrant-env plugin is required and was not found. This script will attempt to install it now.\")\n    if ! $(which vagrant) plugin install \"vagrant-env\"; then\n      (echo >&2 \"Unable to install the vagrant-env plugin. Please try to do so manually and re-run this script.\")\n      exit 1\n    else \n      (echo >&2 \"${GOODTOGO} The vagrant-env plugin was successfully installed!\")\n    fi\n  else\n    (echo >&2 \"${GOODTOGO} The vagrant-env plugin is currently installed\")\n  fi\n}\n\ncheck_ovftool_installed() {\n  if ! which ovftool >/dev/null; then\n    (echo >&2 \"${ERROR} ovftool was not found in your PATH.\")\n    (echo >&2 \"${ERROR} Please correct this before continuing. Exiting.\")\n    (echo >&2 \"${ERROR} Correct this by installing appropriate ovftool version for your environment : https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest\")\n    exit 1\n  else\n    OVFTOOL_VERSION=$(ovftool -v | cut -d ' ' -f 3)\n    (echo >&2 \"${GOODTOGO} ovftool (${OVFTOOL_VERSION}) is installed, make sure that version matches your ESXi environment\")\n  fi\n}\n\n# Check available disk space. Recommend 120GB free, warn if less.\ncheck_disk_free_space() {\n  FREE_DISK_SPACE=$(df -m \"$HOME\" | tr -s ' ' | grep '/' | cut -d ' ' -f 4)\n  if [ \"$FREE_DISK_SPACE\" -lt 120000 ]; then\n    (echo >&2 \"${INFO} Warning: You appear to have less than 120GB of HDD space free on your primary partition. If you are using a separate parition, you may ignore this warning.\\n\")\n  else\n    (echo >&2 \"${GOODTOGO} You have more than 120GB of free space on your primary partition\")\n  fi\n}\n\ncheck_ram_space() {\n  RAM_SPACE=$(free|tr -s ' '|grep Mem|cut -d ' ' -f 2)\n  if [ \"$RAM_SPACE\" -lt 24000000 ]; then\n    (echo >&2 \"${INFO} Warning: You appear to have less than 24GB of RAM on your disk, you should consider running only a part of the lab.\\n\")\n  else\n    (echo >&2 \"${GOODTOGO} You have more than 24GB of ram\")\n  fi\n}\n\nmain() {\n  # Get location of prepare.sh\n  # https://stackoverflow.com/questions/59895/getting-the-source-directory-of-a-bash-script-from-within\n  VAGRANT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n\n  case $PROVIDER in\n    \"virtualbox\")\n      (echo >&2 \"[+] Enumerating virtualbox\")\n      check_virtualbox_installed\n      check_vagrant_path\n      check_vagrant_reload_plugin\n      check_disk_free_space\n      check_ram_space\n      case $ANSIBLE_HOST in\n        \"docker\")\n          check_docker_installed\n          ;;\n        \"local\")\n          check_python_env\n          ;;\n        *)\n          ;;\n      esac\n      ;;\n    \"vmware\")\n      (echo >&2 \"[+] Enumerating vmware\")\n      check_vmware_workstation_installed\n      check_vagrant_path\n      check_vagrant_reload_plugin\n      check_vagrant_vmware_utility_installed\n      check_vmware_desktop_vagrant_plugin_installed\n      check_disk_free_space\n      check_ram_space\n      case $ANSIBLE_HOST in\n        \"docker\")\n          check_docker_installed\n          ;;\n        \"local\")\n          check_python_env\n          ;;\n        *)\n          ;;\n      esac\n      ;;\n    \"vmware_esxi\")\n      (echo >&2 \"[+] Enumerating vmware_esxi\")\n      check_vagrant_path\n      check_vagrant_reload_plugin\n      check_vagrant_esxi_plugin\n      check_vagrant_env_plugin\n      check_ovftool_installed\n      case $ANSIBLE_HOST in\n        \"docker\")\n          check_docker_installed\n          ;;\n        \"local\")\n          check_python_env\n          ;;\n        *)\n          ;;\n      esac\n      ;;\n    \"proxmox\")\n      (echo >&2 \"[+] Enumerating proxmox\")\n      check_packer_path\n      check_terraform_path\n      case $ANSIBLE_HOST in\n        \"docker\")\n          check_docker_installed\n          ;;\n        \"local\")\n          check_python_env\n          ;;\n        *)\n          ;;\n      esac\n      ;;\n    \"azure\")\n      (echo >&2 \"[+] Enumerating azure\")\n      check_azure_installed\n      check_terraform_path\n      check_rsync_path\n      ;;\n    \"aws\")\n      (echo >&2 \"[+] Enumerating aws\")\n      check_aws_installed\n      check_terraform_path\n      check_rsync_path\n      ;;\n    *)\n      print_usage\n      ;;\n  esac\n}\n\nmain \nexit 0\n"
  },
  {
    "path": "scripts/setup_aws.sh",
    "content": "#!/bin/bash\n\n# Install git and python3\nsudo apt-get update\nsudo apt-get install -y git python3-venv python3-pip sshpass\n\n#python3 -m venv .venv\n#source .venv/bin/activate\n\n# Install ansible and pywinrm\npython3 -m pip install --upgrade pip\npython3 -m pip install ansible-core==2.12.6\npython3 -m pip install pywinrm\n\n# Install the required ansible libraries\n/home/goad/.local/bin/ansible-galaxy install -r /home/goad/GOAD/ansible/requirements.yml\n\n# set color\nsudo sed -i '/force_color_prompt=yes/s/^#//g' /home/*/.bashrc\nsudo sed -i '/force_color_prompt=yes/s/^#//g' /root/.bashrc"
  },
  {
    "path": "scripts/setup_azure.sh",
    "content": "#!/bin/bash\n\n# Install git and python3\nsudo apt-get update\nsudo apt-get install -y git python3-venv python3-pip sshpass\n\n#python3 -m venv .venv\n#source .venv/bin/activate\n\n# Install ansible and pywinrm\npython3 -m pip install --upgrade pip\npython3 -m pip install ansible-core==2.12.6\npython3 -m pip install pywinrm\n\n# Install the required ansible libraries\n/home/goad/.local/bin/ansible-galaxy install -r /home/goad/GOAD/ansible/requirements.yml\n\n# set color\nsudo sed -i '/force_color_prompt=yes/s/^#//g' /home/*/.bashrc\nsudo sed -i '/force_color_prompt=yes/s/^#//g' /root/.bashrc"
  },
  {
    "path": "scripts/setup_esxi.sh",
    "content": "#!/bin/bash\n\nif ! command -v sudo &> /dev/null\nthen \n  echo \"sudo not installed, please install before running this script\"\n  exit 1\nfi\n\n# Install git and python3\nsudo apt-get update\n\n######################################################################################################\n# ANSIBLE\nsudo apt install -y git python3-pip python3-venv \n\npython3 -m venv .venv\nsource .venv/bin/activate\n\npython3 -m pip install --upgrade pip\npython3 -m pip install ansible-core==2.12.6\npython3 -m pip install pywinrm\n\n######################################################################################################\n# ANSIBLE Galaxy\nansible-galaxy install -r ansible/requirements.yml\n\necho \"#################################################\"\necho \"You will need to run: source .venv/bin/activate\"\necho \"to get back in the python virtual environment\"\necho \"#################################################\""
  },
  {
    "path": "scripts/setup_local_jumpbox.sh",
    "content": "#!/bin/bash\n\n# Install git and python3\nsudo apt-get update\nsudo apt-get install -y git python3-venv python3-pip git\n\n# git clone goad\nGOAD_REPO=/home/vagrant/GOAD\nGIT_FOLDER=$GOAD_REPO/.git\nif [ ! -d $GIT_FOLDER ]\nthen\n    rm -rf $GOAD_REPO\n    git clone https://github.com/Orange-Cyberdefense/GOAD.git $GOAD_REPO\n    cd $GOAD_REPO\n    # git checkout -b v3-beta origin/v3-beta\nelse\n    cd $GOAD_REPO\n    git pull\nfi\n\n# Install ansible and pywinrm\npython3 -m pip install --upgrade pip\ncd $GOAD_REPO\npython3 -m pip install -r requirements.yml\n\ncd $GOAD_REPO/ansible\n/home/vagrant/.local/bin/ansible-galaxy install -r requirements.yml\n\n# set color\nsudo sed -i '/force_color_prompt=yes/s/^#//g' /home/*/.bashrc\nsudo sed -i '/force_color_prompt=yes/s/^#//g' /root/.bashrc"
  },
  {
    "path": "scripts/setup_proxmox.sh",
    "content": "#!/bin/bash\n\nif ! command -v sudo &> /dev/null\nthen \n  echo \"sudo not installed, please install before running this script\"\n  exit 1\nfi\n\nsudo apt update\nsudo apt install -y git vim tmux curl gnupg software-properties-common mkisofs sshpass\n\n######################################################################################################\n# PACKER & TERRAFORM\n\n# Install the HashiCorp GPG key.\nwget -O- https://apt.releases.hashicorp.com/gpg | sudo \\\ngpg --batch --yes --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg\n\n# Add Hashicorp Source List\necho \"deb [arch=$(dpkg --print-architecture) \\\nsigned-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \\\nhttps://apt.releases.hashicorp.com $(lsb_release -cs) main\" \\\n| sudo tee /etc/apt/sources.list.d/hashicorp.list\n\nsudo apt update && sudo apt install -y packer terraform\n\n######################################################################################################\n# ANSIBLE\nsudo apt install -y python3-pip python3-venv \n\npython3 -m venv .venv\nsource .venv/bin/activate\n\npython3 -m pip install --upgrade pip\npython3 -m pip install ansible-core==2.12.6\npython3 -m pip install pywinrm\n\n######################################################################################################\n# ANSIBLE Galaxy\nansible-galaxy install -r ansible/requirements.yml\n\necho \"#################################################\"\necho \"You will need to run: source .venv/bin/activate\"\necho \"to get back in the python virtual environment\"\necho \"#################################################\"\n"
  },
  {
    "path": "template/provider/aws/instance-init.ps1.tpl",
    "content": "<powershell>\n  [Net.ServicePointManager]::SecurityProtocol = \"tls12, tls11, tls\"\n  curl https://raw.githubusercontent.com/ansible/ansible/38e50c9f819a045ea4d40068f83e78adbfaf2e68/examples/scripts/ConfigureRemotingForAnsible.ps1 -o ConfigureRemotingForAnsible.ps1\n  powershell -ExecutionPolicy Unrestricted -File ConfigureRemotingForAnsible.ps1\n  Set-DnsClient -InterfaceAlias Ethernet -ConnectionSpecificSuffix \"${domain}\"\n  Set-DnsClientGlobalSetting -SuffixSearchList @(\\\"\"${domain}\"\\\")\n  Rename-LocalUser -Name \"Administrator\" -NewName \"${username}\"\n  net user ansible ${password} /add /expires:never /y\n  net localgroup administrators ansible /add\n  net user ${username} ${password} /expires:never /y\n</powershell>\n"
  },
  {
    "path": "template/provider/aws/instance-init.sh.tpl",
    "content": "#!/bin/bash\nusermod -l \"${username}\" ubuntu  \nusermod -d \"/home/${username}\" -m ${username}\nsed -i \"s/ubuntu/${username}/\" /etc/sudoers.d/90-cloud-init-users\necho \"${username}\":\"${password}\" | chpasswd\n\n# Enable password authentication\nsed -i 's/^#PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config\nsed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config\nsed -i 's/^#PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config.d/*.conf\nsed -i 's/^PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config.d/*.conf\nsystemctl restart ssh"
  },
  {
    "path": "template/provider/aws/jumpbox-init.sh.tpl",
    "content": "#!/bin/bash\nusermod -l \"${username}\" ubuntu  \nusermod -d \"/home/${username}\" -m ${username}\nsed -i \"s/ubuntu/${username}/\" /etc/sudoers.d/90-cloud-init-users\n"
  },
  {
    "path": "template/provider/aws/jumpbox.tf",
    "content": "resource \"tls_private_key\" \"ssh\" {\n  algorithm = \"RSA\"\n  rsa_bits  = 4096\n}\n\nresource \"aws_network_interface\" \"goad-vm-nic-jumpbox\" {\n  subnet_id   = aws_subnet.goad_public_network.id\n  private_ips = [\"{{ip_range}}.100\"]\n  security_groups = [aws_security_group.goad_security_group.id]\n  tags = {\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\nresource \"aws_instance\" \"goad-vm-jumpbox\" {\n  ami                    = \"ami-04c332520bd9cedb4\"\n  instance_type          = \"t2.medium\"\n\n  network_interface {\n    network_interface_id = aws_network_interface.goad-vm-nic-jumpbox.id\n    device_index = 0\n  }\n\n  user_data = templatefile(\"${path.module}/jumpbox-init.sh.tpl\", {\n                                username = var.jumpbox_username\n                           })\n\n  key_name = \"{{lab_identifier}}-jumpbox-keypair\"\n  tags = {\n    Name = \"{{lab_name}}-jumpbox\"\n    Lab = \"{{lab_identifier}}\"\n  }\n\n  root_block_device {\n    volume_size = var.jumpbox_disk_size\n    tags = {\n      Name = \"{{lab_name}}-JumpBox-root\"\n      Lab = \"{{lab_identifier}}\"\n    }\n  }\n\n  provisioner \"local-exec\" {\n    command = \"echo '${tls_private_key.ssh.private_key_openssh}' > ../ssh_keys/ubuntu-jumpbox.pem && echo '${tls_private_key.ssh.public_key_openssh}' > ../ssh_keys/ubuntu-jumpbox.pub && chmod 600 ../ssh_keys/*\"\n  }\n}\n\n"
  },
  {
    "path": "template/provider/aws/linux.tf",
    "content": "variable \"linux_vm_config\" {\n  type = map(object({\n    name               = string\n    linux_sku          = string\n    linux_version      = string\n    ami                = string\n    instance_type      = string\n    private_ip_address = string\n    password           = string\n  }))\n\n  default = {\n    {{linux_vms}}\n  }\n}\n\nresource \"tls_private_key\" \"linux_ssh\" {\n  algorithm = \"RSA\"\n  rsa_bits  = 4096\n}\n\n\nresource \"aws_network_interface\" \"linux-goad-vm-nic\" {\n  for_each = var.linux_vm_config\n  subnet_id   = aws_subnet.goad_private_network.id\n  private_ips = [each.value.private_ip_address]\n  security_groups = [aws_security_group.goad_security_group.id]\n  tags = {\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\nresource \"aws_instance\" \"linux-goad-vm\" {\n  for_each = var.linux_vm_config\n\n  ami                    = \"${each.value.ami}\"\n  instance_type          = \"${each.value.instance_type}\"\n\n  network_interface {\n    network_interface_id = aws_network_interface.linux-goad-vm-nic[each.key].id\n    device_index = 0\n  }\n\n  user_data = templatefile(\"${path.module}/instance-init.sh.tpl\", {\n                                username = var.username\n                                password = each.value.password\n                           })\n\n  key_name = \"{{lab_identifier}}-linux-keypair\"\n\n  tags = {\n    Name = \"{{lab_name}}-${each.value.name}\"\n    Lab = \"{{lab_identifier}}\"\n  }\n\n  provisioner \"local-exec\" {\n    command = \"echo '${tls_private_key.linux_ssh.private_key_openssh}' > ../ssh_keys/${each.value.name}_ssh.pem && echo '${tls_private_key.linux_ssh.public_key_openssh}' > ../ssh_keys/${each.value.name}_ssh.pub && chmod 600 ../ssh_keys/*\"\n  }\n}\n\n"
  },
  {
    "path": "template/provider/aws/main.tf",
    "content": "terraform {\n  required_providers {\n    aws = {\n      source  = \"hashicorp/aws\"\n      version = \"= 5.44.0\"\n    }\n  }\n\n  required_version = \">= 0.10.0\"\n}\n\nprovider \"aws\" {\n  region = var.region\n  profile = \"goad\"\n}"
  },
  {
    "path": "template/provider/aws/network.tf",
    "content": "# VPC\nresource \"aws_vpc\" \"goad_vpc\" {\n  cidr_block = var.goad_cidr \n  tags = { \n    Name = \"{{lab_name}}-VPC\"\n    Lab = \"{{lab_identifier}}\"\n  } \n} \n\n\n# Subnets\nresource \"aws_subnet\" \"goad_private_network\" {\n  vpc_id     = aws_vpc.goad_vpc.id\n  cidr_block = var.goad_private_cidr\n  availability_zone = var.zone\n  \n  tags = {\n    Name = \"{{lab_name}}-private-network\"\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\nresource \"aws_subnet\" \"goad_public_network\" {\n  vpc_id     = aws_vpc.goad_vpc.id\n  cidr_block = var.goad_public_cidr\n  availability_zone = var.zone\n  depends_on = [aws_internet_gateway.internet_gateway]\n\n  tags = {\n    Name = \"{{lab_name}}-public-network\"\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\n# Routing\nresource \"aws_default_route_table\" \"goad_default_table\" {\n  default_route_table_id = aws_vpc.goad_vpc.default_route_table_id\n  tags = {\n    Name = \"{{lab_name}} Default Route table\"\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\nresource \"aws_route_table\" \"goad_public_table\" {\n  vpc_id = aws_vpc.goad_vpc.id\n\n  route {\n    cidr_block = \"0.0.0.0/0\"\n    gateway_id = aws_internet_gateway.internet_gateway.id\n  }\n\n  tags = {\n    Name = \"{{lab_name}} Route table\"\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\nresource \"aws_route_table\" \"goad_private_table\" {\n  vpc_id = aws_vpc.goad_vpc.id\n\n  route {\n    cidr_block = \"0.0.0.0/0\"\n    nat_gateway_id = aws_nat_gateway.nat_gateway.id\n  }\n\n  tags = {\n    Name = \"{{lab_name}} Private Route table\"\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\nresource \"aws_route_table_association\" \"goad_private_table_association\" {\n  subnet_id      = aws_subnet.goad_private_network.id\n  route_table_id = aws_route_table.goad_private_table.id\n}\n\nresource \"aws_route_table_association\" \"goad_public_table_association\" {\n  subnet_id      = aws_subnet.goad_public_network.id\n  route_table_id = aws_route_table.goad_public_table.id\n}\n\n# Security group\nresource \"aws_default_security_group\" \"goad_default_security_group\" {\n  vpc_id      = aws_vpc.goad_vpc.id\n\n  tags = {\n    Name = \"{{lab_name}} Default Security Group\"\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\nresource \"aws_security_group\" \"goad_security_group\" {\n  name        = \"{{lab_name}} Security Group\"\n  description = \"Allow traffic necessary to use GOAD\"\n  vpc_id      = aws_vpc.goad_vpc.id\n\n  tags = {\n    Name = \"{{lab_name}} Security Group\"\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\nresource \"aws_vpc_security_group_ingress_rule\" \"allow_whitelist_ingress\" {\n  for_each = var.whitelist_cidr\n  security_group_id = aws_security_group.goad_security_group.id\n  cidr_ipv4         = each.key\n  ip_protocol       = \"-1\"\n}\n\nresource \"aws_vpc_security_group_ingress_rule\" \"allow_goad_ingress\" {\n  security_group_id = aws_security_group.goad_security_group.id\n  cidr_ipv4         = var.goad_cidr\n  ip_protocol       = \"-1\"\n}\n\nresource \"aws_vpc_security_group_egress_rule\" \"allow_goad_egress\" {\n  security_group_id = aws_security_group.goad_security_group.id\n  cidr_ipv4         = var.goad_cidr\n  ip_protocol       = \"-1\"\n}\n\nresource \"aws_vpc_security_group_egress_rule\" \"allow_tcp_internet_http_egress\" {\n  security_group_id = aws_security_group.goad_security_group.id\n  cidr_ipv4         = \"0.0.0.0/0\"\n  ip_protocol       = \"tcp\"\n  from_port         = \"80\"\n  to_port           = \"80\"\n}\n\nresource \"aws_vpc_security_group_egress_rule\" \"allow_tcp_internet_https_egress\" {\n  security_group_id = aws_security_group.goad_security_group.id\n  cidr_ipv4         = \"0.0.0.0/0\"\n  ip_protocol       = \"tcp\"\n  from_port         = \"443\"\n  to_port           = \"443\"\n}\n\nresource \"aws_vpc_security_group_egress_rule\" \"allow_udp_internet_dns_egress\" {\n  security_group_id = aws_security_group.goad_security_group.id\n  cidr_ipv4         = \"0.0.0.0/0\"\n  ip_protocol       = \"udp\"\n  from_port         = \"53\"\n  to_port           = \"53\"\n}\n\nresource \"aws_vpc_security_group_egress_rule\" \"allow_icmp_egress\" {\n  security_group_id = aws_security_group.goad_security_group.id\n  cidr_ipv4         = \"0.0.0.0/0\"\n  ip_protocol       = \"icmp\"\n  from_port           = \"-1\"\n  to_port           = \"-1\"\n}\n\n# Public IPs\nresource \"aws_eip\" \"public_ip\" {\n  domain = \"vpc\"\n\n  instance                  = aws_instance.goad-vm-jumpbox.id\n  associate_with_private_ip = \"{{ip_range}}.100\"\n\n  tags = {\n    Name = \"{{lab_name}} Jumpbox public IP\"\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\nresource \"aws_eip\" \"nat_ip\" {\n  domain = \"vpc\"\n}\n\n# Gateways\nresource \"aws_internet_gateway\" \"internet_gateway\" {\n  vpc_id = aws_vpc.goad_vpc.id\n\n  tags = {\n    Name = \"{{lab_name}} Internet Gateway\"\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\n\nresource \"aws_nat_gateway\" \"nat_gateway\" {\n  allocation_id = aws_eip.nat_ip.id\n  subnet_id     = aws_subnet.goad_public_network.id\n\n  tags = {\n    Name = \"{{lab_name}} NAT Gateway\"\n    Lab = \"{{lab_identifier}}\"\n  }\n\n  depends_on = [aws_internet_gateway.internet_gateway]\n}\n\n"
  },
  {
    "path": "template/provider/aws/outputs.tf",
    "content": "output \"ubuntu-jumpbox-ip\" {\n  value = aws_eip.public_ip.public_ip\n}\n\noutput \"ubuntu-jumpbox-username\" {\n  value = var.jumpbox_username\n}\n\noutput \"vm-config\" {\n  value = var.vm_config\n}\n\noutput \"windows-vm-username\" {\n  value = var.username\n}"
  },
  {
    "path": "template/provider/aws/variables.tf",
    "content": "# Region\nvariable \"region\" {\n  description = \"Where you want to deploy GOAD\"\n  type      = string\n  default   = \"{{config.get_value('aws', 'aws_region', 'eu-west-3')}}\"\n}\n\n# Zone\nvariable \"zone\" {\n  description = \"Where you want to deploy GOAD\"\n  type      = string\n  default   = \"{{config.get_value('aws', 'aws_zone', 'eu-west-3c')}}\"\n}\n\n# CIDRs\nvariable \"goad_cidr\" {\n  description = \"Default CIDR for GOAD\"\n  type    = string\n  default = \"{{ip_range}}.0/24\"\n}\n\nvariable \"goad_public_cidr\" {\n  description = \"Private CIDR for GOAD\"\n  type    = string\n  default = \"{{ip_range}}.64/26\"\n}\n\nvariable \"goad_private_cidr\" {\n  description = \"Private CIDR for GOAD\"\n  type    = string\n  default = \"{{ip_range}}.0/26\"\n}\n\n# Define a CIDR for access to the jumphost!\nvariable \"whitelist_cidr\" {\n  description = \"Whitelisted table IP that can access the Ubuntu jumpbox\"\n  type    = set(string)\n  default = [\"0.0.0.0/0\"]\n}\n\n# Credentials\nvariable \"username\" {\n  description = \"Username for local administrator of Windows VMs - Password is defined in the deploy.tf file for each VM\"\n  type    = string\n  default = \"goadmin\"\n}\n\nvariable \"jumpbox_username\" {\n  description = \"Username for jumpbox SSH user\"\n  type    = string\n  default = \"goad\"\n}\n\nvariable \"jumpbox_disk_size\" {\n  description = \"Jumpbox root disk size, defaults to 30 Go\"\n  type    = number\n  default = 30\n}\n\n# Keys are automagically generated and written in the ssh_keys folder. You can provide your own if you like.\nresource \"aws_key_pair\" \"goad-windows-keypair\" {\n  key_name   = \"{{lab_identifier}}-windows-keypair\"\n  public_key = tls_private_key.windows.public_key_openssh\n}\n\nresource \"aws_key_pair\" \"goad-jumpbox-keypair\" {\n  key_name   = \"{{lab_identifier}}-jumpbox-keypair\"\n  public_key = tls_private_key.ssh.public_key_openssh\n}\n\nresource \"aws_key_pair\" \"goad-linux-keypair\" {\n  key_name   = \"{{lab_identifier}}-linux-keypair\"\n  public_key = tls_private_key.ssh.public_key_openssh\n}\n"
  },
  {
    "path": "template/provider/aws/windows.tf",
    "content": "resource \"tls_private_key\" \"windows\" {\n  algorithm = \"RSA\"\n  rsa_bits  = 4096\n}\n\nvariable \"vm_config\" {\n  type = map(object({\n    name               = string\n    domain             = string\n    windows_sku        = string\n    ami                = string\n    instance_type      = string\n    private_ip_address = string\n    password           = string\n  }))\n\n  default = {\n    {{windows_vms}}\n  }\n}\n\n\nresource \"aws_network_interface\" \"goad-vm-nic\" {\n  for_each = var.vm_config\n  subnet_id   = aws_subnet.goad_private_network.id\n  private_ips = [each.value.private_ip_address]\n  security_groups = [aws_security_group.goad_security_group.id]\n  tags = {\n    Lab = \"{{lab_identifier}}\"\n  }\n}\n\nresource \"aws_instance\" \"goad-vm\" {\n  for_each = var.vm_config\n\n  ami                    = each.value.ami\n  instance_type          = each.value.instance_type\n\n  network_interface {\n    network_interface_id = aws_network_interface.goad-vm-nic[each.key].id\n    device_index = 0\n  }\n\n  user_data = templatefile(\"${path.module}/instance-init.ps1.tpl\", {\n                                username = var.username\n                                password = each.value.password\n                                domain = each.value.domain\n                           })\n\n  key_name = \"{{lab_identifier}}-windows-keypair\"\n\n  tags = {\n    Name = \"{{lab_name}}-${each.value.name}\"\n    Lab = \"{{lab_identifier}}\"\n  }\n\n  provisioner \"local-exec\" {\n    command = \"echo '${tls_private_key.windows.private_key_pem}' > ../ssh_keys/id_rsa_windows && echo '${tls_private_key.windows.public_key_pem}' > ../ssh_keys/id_rsa_windows.pub && chmod 600 ../ssh_keys/id_rsa*\"\n  }\n}\n\n"
  },
  {
    "path": "template/provider/azure/jumpbox.tf",
    "content": "resource \"tls_private_key\" \"ssh\" {\n  algorithm = \"RSA\"\n  rsa_bits  = 4096\n}\n\nresource \"azurerm_public_ip\" \"ubuntu_public_ip\" {\n  name                = \"ubuntu-public-ip\"\n  location            = azurerm_resource_group.resource_group.location\n  resource_group_name = azurerm_resource_group.resource_group.name\n  allocation_method   = \"Static\"\n}\n\nresource \"azurerm_network_interface\" \"ubuntu_jumbox_nic\" {\n  name                = \"ubuntu-jumbox-nic\"\n  location            = azurerm_resource_group.resource_group.location\n  resource_group_name = azurerm_resource_group.resource_group.name\n\n  ip_configuration {\n    name                          = \"ubuntu-jumbox-nic-ipconfig\"\n    subnet_id                     = azurerm_subnet.subnet.id\n    private_ip_address_allocation = \"Static\"\n    private_ip_address            = \"{{ip_range}}.100\"\n    public_ip_address_id          = azurerm_public_ip.ubuntu_public_ip.id\n  }\n}\n\nresource \"azurerm_linux_virtual_machine\" \"jumpbox\" {\n  name                = \"ubuntu-jumpbox\"\n  resource_group_name = azurerm_resource_group.resource_group.name\n  location            = azurerm_resource_group.resource_group.location\n  size                = var.size\n  admin_username      = var.jumpbox_username\n  network_interface_ids = [\n    azurerm_network_interface.ubuntu_jumbox_nic.id,\n  ]\n\n  disable_password_authentication = true\n\n  admin_ssh_key {\n    username   = var.jumpbox_username\n    public_key = tls_private_key.ssh.public_key_openssh\n  }\n\n  os_disk {\n    caching              = \"ReadWrite\"\n    storage_account_type = \"Standard_LRS\"\n  }\n\n  source_image_reference {\n    publisher = \"Canonical\"\n    offer     = \"0001-com-ubuntu-server-jammy\"\n    sku       = \"22_04-lts-gen2\"\n    version   = \"latest\"\n  }\n\n  provisioner \"local-exec\" {\n    command = \"echo '${tls_private_key.ssh.private_key_pem}' > ../ssh_keys/ubuntu-jumpbox.pem && chmod 600 ../ssh_keys/ubuntu-jumpbox.pem\"\n  }\n}\n"
  },
  {
    "path": "template/provider/azure/linux.tf",
    "content": "# find image list:\nvariable \"linux_vm_config\" {\n  type = map(object({\n    name               = string\n    linux_sku          = string\n    linux_offer        = string\n    linux_version      = string\n    private_ip_address = string\n    password           = string\n    size               = string\n  }))\n\n  default = {\n    {{linux_vms}}\n  }\n}\n\nresource \"tls_private_key\" \"linux_ssh\" {\n  algorithm = \"RSA\"\n  rsa_bits  = 4096\n}\n\nresource \"azurerm_linux_virtual_machine\" \"goad-linux-vm\" {\n  for_each = var.linux_vm_config\n\n  name                = \"goad-vm-${each.value.name}\"\n  resource_group_name = azurerm_resource_group.resource_group.name\n  location            = azurerm_resource_group.resource_group.location\n  size                = \"${each.value.size}\"\n  admin_username      = var.username\n  admin_password      = \"${each.value.password}\"\n  network_interface_ids = [\n    azurerm_network_interface.goad-linux-vm-nic[each.key].id,\n  ]\n\n  disable_password_authentication = false\n\n  admin_ssh_key {\n    username   = var.username\n    public_key = tls_private_key.linux_ssh.public_key_openssh\n  }\n\n  os_disk {\n    caching              = \"ReadWrite\"\n    storage_account_type = \"Standard_LRS\"\n  }\n\n  source_image_reference {\n    publisher = \"Canonical\"\n    offer     = each.value.linux_offer #\"0001-com-ubuntu-server-jammy\"\n    sku       = each.value.linux_sku # \"22_04-lts-gen2\"\n    version   = each.value.linux_version # \"latest\"\n  }\n\n  provisioner \"local-exec\" {\n    command = \"echo '${tls_private_key.linux_ssh.private_key_pem}' > ../ssh_keys/${each.value.name}_ssh.pem && chmod 600 ../ssh_keys/${each.value.name}_ssh.pem\"\n  }\n}"
  },
  {
    "path": "template/provider/azure/main.tf",
    "content": "terraform {\n  required_providers {\n    azurerm = {\n      source  = \"hashicorp/azurerm\"\n      version = \"=3.116.0\"\n    }\n  }\n\n  required_version = \">= 0.10.0\"\n}\n\nprovider \"azurerm\" {\n  features {}\n}\n\n\nresource \"azurerm_resource_group\" \"resource_group\" {\n  name     = \"{{lab_identifier}}\"\n  location = var.location\n}"
  },
  {
    "path": "template/provider/azure/network.tf",
    "content": "resource \"azurerm_virtual_network\" \"virtual_network\" {\n  name                = \"{{lab_name}}-virtual-network\"\n  address_space       = [\"{{ip_range}}.0/24\"]\n  location            = azurerm_resource_group.resource_group.location\n  resource_group_name = azurerm_resource_group.resource_group.name\n}\n\nresource \"azurerm_subnet\" \"subnet\" {\n  name                 = \"{{lab_name}}-vm-subnet\"\n  resource_group_name  = azurerm_resource_group.resource_group.name\n  virtual_network_name = azurerm_virtual_network.virtual_network.name\n  address_prefixes     = [\"{{ip_range}}.0/24\"]\n}\n\nresource \"azurerm_network_security_group\" \"nsg\" {\n  name                 = \"{{lab_name}}-subnet-nsg\"\n  location             = azurerm_resource_group.resource_group.location\n  resource_group_name  = azurerm_resource_group.resource_group.name\n\n  security_rule {\n    name                          = \"AllowSSHInboundOnly\"\n    priority                      = 100\n    direction                     = \"Inbound\"\n    access                        = \"Allow\"\n    protocol                      = \"Tcp\"\n    source_port_range             = \"*\"\n    destination_port_range        = \"22\"\n    source_address_prefix         = \"*\"\n    destination_address_prefix    = \"*\"\n  }\n}\n\nresource \"azurerm_subnet_network_security_group_association\" \"nsg_association\" {\n  subnet_id                       = azurerm_subnet.subnet.id\n  network_security_group_id       = azurerm_network_security_group.nsg.id\n}\n\nresource \"azurerm_network_interface\" \"goad-vm-nic\" {\n  for_each = var.vm_config\n\n  name                = \"{{lab_name}}-vm-${each.value.name}-nic\"\n  location            = azurerm_resource_group.resource_group.location\n  resource_group_name = azurerm_resource_group.resource_group.name\n\n  ip_configuration {\n    name                          = \"{{lab_name}}-vm-${each.value.name}-nic-ipconfig\"\n    subnet_id                     = azurerm_subnet.subnet.id\n    private_ip_address_allocation = \"Static\"\n    private_ip_address            = each.value.private_ip_address\n  }\n}\n\nresource \"azurerm_network_interface\" \"goad-linux-vm-nic\" {\n  for_each = var.linux_vm_config\n\n  name                = \"{{lab_name}}-vm-${each.value.name}-nic\"\n  location            = azurerm_resource_group.resource_group.location\n  resource_group_name = azurerm_resource_group.resource_group.name\n\n  ip_configuration {\n    name                          = \"{{lab_name}}-vm-${each.value.name}-nic-ipconfig\"\n    subnet_id                     = azurerm_subnet.subnet.id\n    private_ip_address_allocation = \"Static\"\n    private_ip_address            = each.value.private_ip_address\n  }\n}\n"
  },
  {
    "path": "template/provider/azure/outputs.tf",
    "content": "output \"ubuntu-jumpbox-ip\" {\n  value = azurerm_linux_virtual_machine.jumpbox.public_ip_address\n}\n\noutput \"ubuntu-jumpbox-username\" {\n  value = azurerm_linux_virtual_machine.jumpbox.admin_username\n}\n\noutput \"vm-config\" {\n  value = var.vm_config\n}\n\noutput \"windows-vm-username\" {\n  value = var.username\n}"
  },
  {
    "path": "template/provider/azure/variables.tf",
    "content": "variable \"location\" {\n  type    = string\n  default = \"{{config.get_value('azure', 'az_location', 'westeurope')}}\"\n}\n\n# default size : 2cpu / 4GB\nvariable \"size\" {\n  type    = string\n  default = \"Standard_B2s\"\n}\n\nvariable \"username\" {\n  type    = string\n  default = \"goadmin\"\n}\n\nvariable \"password\" {\n  description = \"Password of the windows virtual machine admin user\"\n  type    = string\n  default = \"goadmin\"\n}\n\nvariable \"jumpbox_username\" {\n  type    = string\n  default = \"goad\"\n}\n"
  },
  {
    "path": "template/provider/azure/windows.tf",
    "content": "# find image list:\n# az vm image list --location \"west europe\" --publisher \"MicrosoftWindowsServer\" --offer \"WindowsServer\" --sku \"2019-Datacenter\" --all -o table\nvariable \"vm_config\" {\n  type = map(object({\n    name               = string\n    publisher          = string\n    offer              = string\n    windows_sku        = string\n    windows_version    = string\n    private_ip_address = string\n    password           = string\n    size               = string\n  }))\n\n  default = {\n    {{windows_vms}}\n  }\n}\n\nresource \"azurerm_windows_virtual_machine\" \"goad-vm\" {\n  for_each = var.vm_config\n\n  name                = \"goad-vm-${each.value.name}\"\n  location            = azurerm_resource_group.resource_group.location\n  resource_group_name = azurerm_resource_group.resource_group.name\n  size                = \"${each.value.size}\"\n  admin_username      = var.username\n  admin_password      = \"${each.value.password}\"\n  network_interface_ids = [\n    azurerm_network_interface.goad-vm-nic[each.key].id,\n  ]\n\n  os_disk {\n    caching              = \"ReadWrite\"\n    storage_account_type = \"Standard_LRS\"\n  }\n\n  source_image_reference {\n    publisher = each.value.publisher\n    offer     = each.value.offer\n    sku       = each.value.windows_sku\n    version   = each.value.windows_version # \"latest\"\n  }\n}\n\nresource \"azurerm_virtual_machine_extension\" \"goad-vm-ext\" {\n  for_each = var.vm_config\n\n  name                 = \"${each.value.name}-ansible-prep\"\n  virtual_machine_id   = azurerm_windows_virtual_machine.goad-vm[each.key].id\n  publisher            = \"Microsoft.Compute\"\n  type                 = \"CustomScriptExtension\"\n  type_handler_version = \"1.9\"\n\n  settings = <<SETTINGS\n  {\n    \"fileUris\": [\"https://raw.githubusercontent.com/ansible/ansible/38e50c9f819a045ea4d40068f83e78adbfaf2e68/examples/scripts/ConfigureRemotingForAnsible.ps1\"],\n    \"commandToExecute\": \"net user ansible ${each.value.password} /add /expires:never /y && net localgroup administrators ansible /add && powershell -ExecutionPolicy Unrestricted -File ConfigureRemotingForAnsible.ps1\"\n  }\n  SETTINGS\n}"
  },
  {
    "path": "template/provider/ludus/config.yml",
    "content": "{{lab}}\n{{extensions}}"
  },
  {
    "path": "template/provider/proxmox/linux.tf",
    "content": "variable \"linux_vm_config\" {\n  type = map(object({\n    name               = string\n    desc               = string\n    cores              = number\n    memory             = number\n    clone              = string\n    dns                = string\n    ip                 = string\n    gateway            = string\n  }))\n\n  default = {\n    {{linux_vms}}\n  }\n}\n\nresource \"proxmox_virtual_environment_vm\" \"bgp-linux\" {\n  for_each = var.linux_vm_config\n\n    name = each.value.name\n    description = each.value.desc\n    node_name   = var.pm_node\n    pool_id     = var.pm_pool\n\n    operating_system {\n      type = \"l26\"\n    }\n\n    cpu {\n      cores   = each.value.cores\n      sockets = 1\n    }\n\n    memory {\n      dedicated = each.value.memory\n    }\n\n    clone {\n      vm_id = lookup(var.vm_template_id, each.value.clone, -1)\n      full  = var.pm_full_clone\n      retries = 2\n    }\n\n    agent {\n      # read 'Qemu guest agent' section, change to true only when ready\n      enabled = true\n    }\n\n    network_device {\n      bridge  = var.network_bridge\n      model   = var.network_model\n      vlan_id = var.network_vlan\n    }\n\n    lifecycle {\n      ignore_changes = [\n        vga,\n      ]\n    }\n\n    initialization {\n      datastore_id = var.storage\n      dns {\n        servers = [\n          each.value.dns\n        ]\n      }\n      ip_config {\n        ipv4 {\n          address = each.value.ip\n          gateway = each.value.gateway\n        }\n      }\n    }\n}\n"
  },
  {
    "path": "template/provider/proxmox/main.tf",
    "content": "terraform {\n  required_providers {\n    proxmox = {\n      source  = \"bpg/proxmox\"\n      version = \"0.65.0\"\n    }\n  }\n}\n\nprovider \"proxmox\" {\n  endpoint = var.pm_api_url\n  username = var.pm_user\n  password = var.pm_password\n  insecure = true\n}\n"
  },
  {
    "path": "template/provider/proxmox/variables.tf",
    "content": "variable \"pm_api_url\" {\n  default = \"{{config.get_value('proxmox', 'pm_api_url', 'https://192.168.1.1:8006/api2/json')}}\"\n}\n\nvariable \"pm_user\" {\n  default = \"{{config.get_value('proxmox', 'pm_user', 'infra_as_code@pve')}}\"\n}\n\nvariable \"pm_password\" {\n    type = string\n    sensitive = true\n}\n\nvariable \"pm_node\" {\n  default = \"{{config.get_value('proxmox', 'pm_node', 'GOAD')}}\"\n}\n\nvariable \"pm_pool\" {\n  default = \"{{config.get_value('proxmox', 'pm_pool', 'GOAD')}}\"\n}\n\nvariable \"pm_full_clone\" {\n  default = \"{{config.get_value('proxmox', 'pm_full_clone', 'false')}}\"\n}\n\n# change this value with the id of your templates (win10 can be ignored if not used)\nvariable \"vm_template_id\" {\n  type = map(number)\n\n  # set the ids according to your templates\n  default = {\n      \"WinServer2019_x64\"  = {{config.get_value('proxmox_templates_id', 'Winserver2019_x64', 201900)}}\n      \"WinServer2019_x64_utd\"  = {{config.get_value('proxmox_templates_id', 'WinServer2019_x64_utd', 201901)}}\n      \"WinServer2016_x64\"  = {{config.get_value('proxmox_templates_id', 'WinServer2016_x64', 201600)}}\n      \"WinServer2022_x64\"  = {{config.get_value('proxmox_templates_id', 'WinServer2022_x64', 202201)}}\n      \"WinServer2025_x64\"  = {{config.get_value('proxmox_templates_id', 'WinServer2025_x64', 202501)}}\n      \"Windows10_22h2_x64\" = {{config.get_value('proxmox_templates_id', 'Windows10_22h2_x64', 102221)}}\n      \"Windows11_23h2_x64\" = {{config.get_value('proxmox_templates_id', 'Windows11_23h2_x64', 112321)}}\n      \"Windows11_24h2_x64\" = {{config.get_value('proxmox_templates_id', 'Windows11_24h2_x64', 112421)}}\n      \"Windows11_25h2_x64\" = {{config.get_value('proxmox_templates_id', 'Windows11_25h2_x64', 112521)}}\n      \"Ubuntu_2204_x64\"    = {{config.get_value('proxmox_templates_id', 'Ubuntu_2204_x64', 922040)}}\n      \"Ubuntu_2404_x64\"    = {{config.get_value('proxmox_templates_id', 'Ubuntu_2404_x64', 924040)}}\n  }\n}\n\nvariable \"storage\" {\n  # change this with the name of the storage you use\n  default = \"{{config.get_value('proxmox', 'pm_storage', 'local')}}\"\n}\n\nvariable \"network_bridge\" {\n  default = \"{{config.get_value('proxmox', 'pm_network_bridge', 'vmbr3')}}\"\n}\n\nvariable \"network_model\" {\n  default = \"{{config.get_value('proxmox', 'pm_network_model', 'e1000')}}\"\n}\n\nvariable \"network_vlan\" {\n  default = {{config.get_value('proxmox', 'pm_vlan', 10)}}\n}\n"
  },
  {
    "path": "template/provider/proxmox/windows.tf",
    "content": "variable \"vm_config\" {\n  type = map(object({\n    name               = string\n    desc               = string\n    cores              = number\n    memory             = number\n    clone              = string\n    dns                = string\n    ip                 = string\n    gateway            = string\n    os                 = optional(string, \"win10\")\n  }))\n\n  default = {\n    {{windows_vms}}\n  }\n}\n\nresource \"proxmox_virtual_environment_vm\" \"bgp\" {\n  for_each = var.vm_config\n\n    name = each.value.name\n    description = each.value.desc\n    node_name   = var.pm_node\n    pool_id     = var.pm_pool\n\n    operating_system {\n      type = each.value.os\n    }\n\n    cpu {\n      cores   = each.value.cores\n      sockets = 1\n      type    = \"host\"\n    }\n\n    memory {\n      dedicated = each.value.memory\n    }\n\n    clone {\n      vm_id = lookup(var.vm_template_id, each.value.clone, -1)\n      full  = var.pm_full_clone\n      retries = 2\n    }\n\n    agent {\n      # read 'Qemu guest agent' section, change to true only when ready\n      enabled = true\n    }\n\n    network_device {\n      bridge  = var.network_bridge\n      model   = var.network_model\n      vlan_id = var.network_vlan\n    }\n\n    lifecycle {\n      ignore_changes = [\n        vga,\n      ]\n    }\n\n    initialization {\n      datastore_id = var.storage\n      dns {\n        servers = [\n          each.value.dns\n        ]\n      }\n      ip_config {\n        ipv4 {\n          address = each.value.ip\n          gateway = each.value.gateway\n        }\n      }\n    }\n}\n\n# # \"Telmate/proxmox\" \"3.0.1-rc1\" template (change clone value to template name to use it and change the provider in main)\n# resource \"proxmox_vm_qemu\" \"telmate-proxmox8\" {\n#     for_each = var.vm_config\n# \n#     name = each.value.name\n#     desc = each.value.desc\n#     qemu_os = \"win10\"\n#     target_node = var.pm_node\n#     sockets = 1\n#     cores = each.value.cores\n#     memory = each.value.memory\n#     agent = 1\n#     clone = lookup(var.vm_template_name, each.value.clone, \"\")\n#     full_clone = var.pm_full_clone\n#     os_type     = \"cloud-init\"\n#     boot        = \"order=sata0;ide3\"\n#     # disk type need to match with disk type in template, in this case sata0\n#     bootdisk    = \"sata0\"\n#     disks{\n#       sata {\n#         sata0 {\n#           disk {\n#             size      = 40\n#             storage   = var.storage\n#           }\n#         }\n#       }\n#     }\n#     # Specify the cloud-init cdrom storage\n#     cloudinit_cdrom_storage = var.storage\n#     network {\n#       bridge    = var.network_bridge\n#       model     = var.network_model\n#       tag       = var.network_vlan\n#     }\n#     nameserver = each.value.dns\n#     ipconfig0 = \"ip=${each.value.ip},gw=${each.value.gateway}\"\n# }\n# \n\n\n# # old telmate template (change clone value to template name to use it) and change the provider in main\n# resource \"proxmox_vm_qemu\" \"telmate-proxmox7\" {\n#     for_each = var.vm_config\n# \n#     name = each.value.name\n#     desc = each.value.desc\n#     qemu_os = \"win10\"\n#     target_node = var.pm_node\n#     pool = var.pm_pool\n#     sockets = 1\n#     cores = each.value.cores\n#     memory = each.value.memory\n#     agent = 1\n#     clone = lookup(var.vm_template_name, each.value.clone, \"\")\n#     full_clone = var.pm_full_clone\n# \n#     network {\n#       bridge    = var.network_bridge\n#       model     = var.network_model\n#       tag       = var.network_vlan\n#     }\n#     \n#     lifecycle {\n#       ignore_changes = [\n#         disk,\n#       ]\n#     }\n#     nameserver = each.value.dns\n#     ipconfig0 = \"ip=${each.value.ip},gw=${each.value.gateway}\"\n# }"
  },
  {
    "path": "template/provider/virtualbox/Vagrantfile",
    "content": "Vagrant.configure(\"2\") do |config|\n\n# Uncomment this depending on the provider you want to use\nENV['VAGRANT_DEFAULT_PROVIDER'] = 'virtualbox'\n\n{{lab}}\n\n{{extensions}}\n\n{% if use_provisioning_vm %}\nboxes.append(\n    { :name => \"PROVISIONING\",\n      :ip => \"{{ip_range}}.3\",\n      :box => \"bento/ubuntu-22.04\",\n      :os => \"linux\",\n      :cpus => 2,\n      :mem => 2000,\n      :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n    }\n)\n{% endif %}\n\n  # disable rdp forwarded port inherited from StefanScherer box\n  config.vm.network :forwarded_port, guest: 3389, host: 3389, id: \"rdp\", auto_correct: true, disabled: true\n\n  # no autoupdate if vagrant-vbguest is installed\n  if Vagrant.has_plugin?(\"vagrant-vbguest\") then\n    config.vbguest.auto_update = false\n  end\n\n  config.vm.boot_timeout = 600\n  config.vm.graceful_halt_timeout = 600\n  config.winrm.retry_limit = 30\n  config.winrm.retry_delay = 10\n  config.winrm.ssl_peer_verification = false\n\n  boxes.each do |box|\n    config.vm.define box[:name] do |target|\n      # BOX\n      target.vm.provider \"virtualbox\" do |v|\n        v.name = box[:name]\n        {% if not use_provisioning_vm %}\n        v.customize [\"modifyvm\", :id, \"--groups\", \"/GOAD\"]\n        {% endif %}\n        v.memory = box[:mem]\n        v.cpus = box[:cpus]\n      end\n      target.vm.box_download_insecure = box[:box]\n      target.vm.box = box[:box]\n      if box.has_key?(:box_version)\n        target.vm.box_version = box[:box_version]\n      end\n\n      # issues/49\n      target.vm.synced_folder '.', '/vagrant', disabled: true\n\n      # IP\n      target.vm.network :private_network, ip: box[:ip]\n\n      # OS specific\n      if box[:os] == \"windows\"\n        target.vm.guest = :windows\n        target.vm.communicator = \"winrm\"\n        target.vm.provision :shell, :path => \"../../../vagrant/Install-WMF3Hotfix.ps1\", privileged: false\n        target.vm.provision :shell, :path => \"../../../vagrant/ConfigureRemotingForAnsible.ps1\", privileged: false\n\n        # fix ip for vmware\n        if ENV['VAGRANT_DEFAULT_PROVIDER'] == \"vmware_desktop\"\n          target.vm.provision :shell, :path => \"../../../vagrant/fix_ip.ps1\", privileged: false, args: box[:ip]\n        end\n\n      else\n        target.vm.communicator = \"ssh\"\n      end\n\n      if box.has_key?(:forwarded_port)\n        # forwarded port explicit\n        box[:forwarded_port] do |forwarded_port|\n          target.vm.network :forwarded_port, guest: forwarded_port[:guest], host: forwarded_port[:host], host_ip: \"127.0.0.1\", id: forwarded_port[:id]\n        end\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "template/provider/vmware/Vagrantfile",
    "content": "Vagrant.configure(\"2\") do |config|\n\nENV['VAGRANT_DEFAULT_PROVIDER'] = 'vmware_desktop'\n\n{{lab}}\n\n{{extensions}}\n\n{% if use_provisioning_vm %}\nboxes.append(\n    { :name => \"PROVISIONING\",\n      :ip => \"{{ip_range}}.3\",\n      :box => \"bento/ubuntu-22.04\",\n      :box_version => \"202401.31.0\",\n      :os => \"linux\",\n      :cpus => 2,\n      :mem => 2000,\n      :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n    }\n)\n{% endif %}\n\n  config.vm.provider \"vmware_desktop\" do |v|\n    v.force_vmware_license = \"workstation\"  # force the licence for fix some vagrant plugin issue\n    # v.gui = true\n  end\n\n  # disable rdp forwarded port inherited from StefanScherer box\n  config.vm.network :forwarded_port, guest: 3389, host: 3389, id: \"rdp\", auto_correct: true, disabled: true\n\n  # no autoupdate if vagrant-vbguest is installed\n  if Vagrant.has_plugin?(\"vagrant-vbguest\") then\n    config.vbguest.auto_update = false\n  end\n\n  config.vm.boot_timeout = 600\n  config.vm.graceful_halt_timeout = 600\n  config.winrm.retry_limit = 30\n  config.winrm.retry_delay = 10\n\n  boxes.each do |box|\n    config.vm.define box[:name] do |target|\n      # BOX\n      target.vm.provider \"vmware_desktop\" do |v|\n        v.vmx[\"memsize\"] = box[:mem]\n        v.vmx[\"numvcpus\"] = box[:cpus]\n      end\n\n      target.vm.box_download_insecure = box[:box]\n      target.vm.box = box[:box]\n      if box.has_key?(:box_version)\n        target.vm.box_version = box[:box_version]\n      end\n\n      # issues/49\n      target.vm.synced_folder '.', '/vagrant', disabled: true\n\n      # IP\n      target.vm.network :private_network, ip: box[:ip]\n\n      # OS specific\n      if box[:os] == \"windows\"\n        target.vm.guest = :windows\n        target.vm.communicator = \"winrm\"\n        target.vm.provision :shell, :path => \"../../../vagrant/Install-WMF3Hotfix.ps1\", privileged: false\n        target.vm.provision :shell, :path => \"../../../vagrant/ConfigureRemotingForAnsible.ps1\", privileged: false\n\n        # fix ip for vmware\n        if ENV['VAGRANT_DEFAULT_PROVIDER'] == \"vmware_desktop\"\n          target.vm.provision :shell, :path => \"../../../vagrant/fix_ip.ps1\", privileged: false, args: box[:ip]\n        end\n      else\n        target.vm.communicator = \"ssh\"\n      end\n\n      if box.has_key?(:forwarded_port)\n        # forwarded port explicit\n        box[:forwarded_port] do |forwarded_port|\n          target.vm.network :forwarded_port, guest: forwarded_port[:guest], host: forwarded_port[:host], host_ip: \"127.0.0.1\", id: forwarded_port[:id]\n        end\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "template/provider/vmware_esxi/Vagrantfile",
    "content": "Vagrant.configure(\"2\") do |config|\n\nENV['VAGRANT_DEFAULT_PROVIDER'] = 'vmware_esxi'\n\n{{lab}}\n\n{{extensions}}\n\n# auto-load .env if vagrant-env installed\nif Vagrant.has_plugin?(\"vagrant-env\") then\n  config.env.enable # Enable vagrant-env(.env)\nend\n\n{% if use_provisioning_vm %}\nboxes.append(\n    { :name => \"PROVISIONING\",\n      :ip => \"{{ip_range}}.3\",\n      :box => \"bento/ubuntu-22.04\",\n      :box_version => \"202401.31.0\",\n      :os => \"linux\",\n      :cpus => 2,\n      :mem => 2000,\n      :forwarded_port => [ {:guest => 22, :host => 2210, :id => \"ssh\"} ]\n    }\n)\n{% endif %}\n\n  # disable rdp forwarded port inherited from StefanScherer box\n  config.vm.network :forwarded_port, guest: 3389, host: 3389, id: \"rdp\", auto_correct: true, disabled: true\n\n  # no autoupdate if vagrant-vbguest is installed\n  if Vagrant.has_plugin?(\"vagrant-vbguest\") then\n    config.vbguest.auto_update = false\n  end\n\n  config.vm.boot_timeout = 600\n  config.vm.graceful_halt_timeout = 600\n  config.winrm.retry_limit = 30\n  config.winrm.retry_delay = 10\n\n  boxes.each do |box|\n    config.vm.define box[:name] do |target|\n      # BOX\n      target.vm.provider :vmware_esxi do |v|\n        v.esxi_hostname         = ENV['GOAD_VAGRANT_ESXIHOSTNAME']\n        v.esxi_username         = ENV['GOAD_VAGRANT_ESXIUSERNAME']\n        v.esxi_password         = 'env:GOAD_VAGRANT_ESXIPASSWORD'\n        v.esxi_virtual_network  = [ ENV['GOAD_VAGRANT_ESXINETNAT'], ENV['GOAD_VAGRANT_ESXINETDOM'] ]\n        v.guest_numvcpus        = '4'\n        v.guest_memsize         = '6000'\n        v.guest_name            = box[:name]\n        v.esxi_disk_store       = ENV['GOAD_VAGRANT_ESXISTORE']\n      end\n\n      target.vm.box_download_insecure = box[:box]\n      target.vm.box = box[:box]\n      if box.has_key?(:box_version)\n        target.vm.box_version = box[:box_version]\n      end\n\n      # issues/49\n      target.vm.synced_folder '.', '/vagrant', disabled: true\n\n      # IP\n      target.vm.network :private_network, ip: box[:ip]\n\n      # OS specific\n      if box[:os] == \"windows\"\n        target.vm.guest = :windows\n        target.vm.communicator = \"winrm\"\n        target.vm.provision :shell, :path => \"../../../vagrant/Install-WMF3Hotfix.ps1\", privileged: false\n        target.vm.provision :shell, :path => \"../../../vagrant/ConfigureRemotingForAnsible.ps1\", privileged: false\n\n        # fix ip for vmware\n        if ENV['VAGRANT_DEFAULT_PROVIDER'] == \"vmware_esxi\"\n          target.vm.provision :shell, :path => \"../../../vagrant/fix_ip.ps1\", privileged: false, args: box[:ip]\n        end\n      else\n        target.vm.communicator = \"ssh\"\n      end\n\n      if box.has_key?(:forwarded_port)\n        # forwarded port explicit\n        box[:forwarded_port] do |forwarded_port|\n          target.vm.network :forwarded_port, guest: forwarded_port[:guest], host: forwarded_port[:host], host_ip: \"127.0.0.1\", id: forwarded_port[:id]\n        end\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "vagrant/ConfigureRemotingForAnsible.ps1",
    "content": "#Requires -Version 3.0\n\n# Configure a Windows host for remote management with Ansible\n# -----------------------------------------------------------\n#\n# This script checks the current WinRM (PS Remoting) configuration and makes\n# the necessary changes to allow Ansible to connect, authenticate and\n# execute PowerShell commands.\n#\n# All events are logged to the Windows EventLog, useful for unattended runs.\n#\n# Use option -Verbose in order to see the verbose output messages.\n#\n# Use option -CertValidityDays to specify how long this certificate is valid\n# starting from today. So you would specify -CertValidityDays 3650 to get\n# a 10-year valid certificate.\n#\n# Use option -ForceNewSSLCert if the system has been SysPreped and a new\n# SSL Certificate must be forced on the WinRM Listener when re-running this\n# script. This is necessary when a new SID and CN name is created.\n#\n# Use option -EnableCredSSP to enable CredSSP as an authentication option.\n#\n# Use option -DisableBasicAuth to disable basic authentication.\n#\n# Use option -SkipNetworkProfileCheck to skip the network profile check.\n# Without specifying this the script will only run if the device's interfaces\n# are in DOMAIN or PRIVATE zones.  Provide this switch if you want to enable\n# WinRM on a device with an interface in PUBLIC zone.\n#\n# Use option -SubjectName to specify the CN name of the certificate. This\n# defaults to the system's hostname and generally should not be specified.\n\n# Written by Trond Hindenes <trond@hindenes.com>\n# Updated by Chris Church <cchurch@ansible.com>\n# Updated by Michael Crilly <mike@autologic.cm>\n# Updated by Anton Ouzounov <Anton.Ouzounov@careerbuilder.com>\n# Updated by Nicolas Simond <contact@nicolas-simond.com>\n# Updated by Dag Wieërs <dag@wieers.com>\n# Updated by Jordan Borean <jborean93@gmail.com>\n# Updated by Erwan Quélin <erwan.quelin@gmail.com>\n# Updated by David Norman <david@dkn.email>\n#\n# Version 1.0 - 2014-07-06\n# Version 1.1 - 2014-11-11\n# Version 1.2 - 2015-05-15\n# Version 1.3 - 2016-04-04\n# Version 1.4 - 2017-01-05\n# Version 1.5 - 2017-02-09\n# Version 1.6 - 2017-04-18\n# Version 1.7 - 2017-11-23\n# Version 1.8 - 2018-02-23\n# Version 1.9 - 2018-09-21\n\n# Support -Verbose option\n[CmdletBinding()]\n\nParam (\n    [string]$SubjectName = $env:COMPUTERNAME,\n    [int]$CertValidityDays = 1095,\n    [switch]$SkipNetworkProfileCheck,\n    $CreateSelfSignedCert = $true,\n    [switch]$ForceNewSSLCert,\n    [switch]$GlobalHttpFirewallAccess,\n    [switch]$DisableBasicAuth = $false,\n    [switch]$EnableCredSSP\n)\n\nFunction Write-Log\n{\n    $Message = $args[0]\n    Write-EventLog -LogName Application -Source $EventSource -EntryType Information -EventId 1 -Message $Message\n}\n\nFunction Write-VerboseLog\n{\n    $Message = $args[0]\n    Write-Verbose $Message\n    Write-Log $Message\n}\n\nFunction Write-HostLog\n{\n    $Message = $args[0]\n    Write-Output $Message\n    Write-Log $Message\n}\n\nFunction New-LegacySelfSignedCert\n{\n    Param (\n        [string]$SubjectName,\n        [int]$ValidDays = 1095\n    )\n\n    $hostnonFQDN = $env:computerName\n    $hostFQDN = [System.Net.Dns]::GetHostByName(($env:computerName)).Hostname\n    $SignatureAlgorithm = \"SHA256\"\n\n    $name = New-Object -COM \"X509Enrollment.CX500DistinguishedName.1\"\n    $name.Encode(\"CN=$SubjectName\", 0)\n\n    $key = New-Object -COM \"X509Enrollment.CX509PrivateKey.1\"\n    $key.ProviderName = \"Microsoft Enhanced RSA and AES Cryptographic Provider\"\n    $key.KeySpec = 1\n    $key.Length = 4096\n    $key.SecurityDescriptor = \"D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)\"\n    $key.MachineContext = 1\n    $key.Create()\n\n    $serverauthoid = New-Object -COM \"X509Enrollment.CObjectId.1\"\n    $serverauthoid.InitializeFromValue(\"1.3.6.1.5.5.7.3.1\")\n    $ekuoids = New-Object -COM \"X509Enrollment.CObjectIds.1\"\n    $ekuoids.Add($serverauthoid)\n    $ekuext = New-Object -COM \"X509Enrollment.CX509ExtensionEnhancedKeyUsage.1\"\n    $ekuext.InitializeEncode($ekuoids)\n\n    $cert = New-Object -COM \"X509Enrollment.CX509CertificateRequestCertificate.1\"\n    $cert.InitializeFromPrivateKey(2, $key, \"\")\n    $cert.Subject = $name\n    $cert.Issuer = $cert.Subject\n    $cert.NotBefore = (Get-Date).AddDays(-1)\n    $cert.NotAfter = $cert.NotBefore.AddDays($ValidDays)\n\n    $SigOID = New-Object -ComObject X509Enrollment.CObjectId\n    $SigOID.InitializeFromValue(([Security.Cryptography.Oid]$SignatureAlgorithm).Value)\n\n    [string[]] $AlternativeName  += $hostnonFQDN\n    $AlternativeName += $hostFQDN\n    $IAlternativeNames = New-Object -ComObject X509Enrollment.CAlternativeNames\n\n    foreach ($AN in $AlternativeName)\n    {\n        $AltName = New-Object -ComObject X509Enrollment.CAlternativeName\n        $AltName.InitializeFromString(0x3,$AN)\n        $IAlternativeNames.Add($AltName)\n    }\n\n    $SubjectAlternativeName = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames\n    $SubjectAlternativeName.InitializeEncode($IAlternativeNames)\n\n    [String[]]$KeyUsage = (\"DigitalSignature\", \"KeyEncipherment\")\n    $KeyUsageObj = New-Object -ComObject X509Enrollment.CX509ExtensionKeyUsage\n    $KeyUsageObj.InitializeEncode([int][Security.Cryptography.X509Certificates.X509KeyUsageFlags]($KeyUsage))\n    $KeyUsageObj.Critical = $true\n\n    $cert.X509Extensions.Add($KeyUsageObj)\n    $cert.X509Extensions.Add($ekuext)\n    $cert.SignatureInformation.HashAlgorithm = $SigOID\n    $CERT.X509Extensions.Add($SubjectAlternativeName)\n    $cert.Encode()\n\n    $enrollment = New-Object -COM \"X509Enrollment.CX509Enrollment.1\"\n    $enrollment.InitializeFromRequest($cert)\n    $certdata = $enrollment.CreateRequest(0)\n    $enrollment.InstallResponse(2, $certdata, 0, \"\")\n\n    # extract/return the thumbprint from the generated cert\n    $parsed_cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2\n    $parsed_cert.Import([System.Text.Encoding]::UTF8.GetBytes($certdata))\n\n    return $parsed_cert.Thumbprint\n}\n\nFunction Enable-GlobalHttpFirewallAccess\n{\n    Write-Verbose \"Forcing global HTTP firewall access\"\n    # this is a fairly naive implementation; could be more sophisticated about rule matching/collapsing\n    $fw = New-Object -ComObject HNetCfg.FWPolicy2\n\n    # try to find/enable the default rule first\n    $add_rule = $false\n    $matching_rules = $fw.Rules | Where-Object  { $_.Name -eq \"Windows Remote Management (HTTP-In)\" }\n    $rule = $null\n    If ($matching_rules) {\n        If ($matching_rules -isnot [Array]) {\n            Write-Verbose \"Editing existing single HTTP firewall rule\"\n            $rule = $matching_rules\n        }\n        Else {\n            # try to find one with the All or Public profile first\n            Write-Verbose \"Found multiple existing HTTP firewall rules...\"\n            $rule = $matching_rules | ForEach-Object { $_.Profiles -band 4 }[0]\n\n            If (-not $rule -or $rule -is [Array]) {\n                Write-Verbose \"Editing an arbitrary single HTTP firewall rule (multiple existed)\"\n                # oh well, just pick the first one\n                $rule = $matching_rules[0]\n            }\n        }\n    }\n\n    If (-not $rule) {\n        Write-Verbose \"Creating a new HTTP firewall rule\"\n        $rule = New-Object -ComObject HNetCfg.FWRule\n        $rule.Name = \"Windows Remote Management (HTTP-In)\"\n        $rule.Description = \"Inbound rule for Windows Remote Management via WS-Management. [TCP 5985]\"\n        $add_rule = $true\n    }\n\n    $rule.Profiles = 0x7FFFFFFF\n    $rule.Protocol = 6\n    $rule.LocalPorts = 5985\n    $rule.RemotePorts = \"*\"\n    $rule.LocalAddresses = \"*\"\n    $rule.RemoteAddresses = \"*\"\n    $rule.Enabled = $true\n    $rule.Direction = 1\n    $rule.Action = 1\n    $rule.Grouping = \"Windows Remote Management\"\n\n    If ($add_rule) {\n        $fw.Rules.Add($rule)\n    }\n\n    Write-Verbose \"HTTP firewall rule $($rule.Name) updated\"\n}\n\n# Setup error handling.\nTrap\n{\n    $_\n    Exit 1\n}\n$ErrorActionPreference = \"Stop\"\n\n# Get the ID and security principal of the current user account\n$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()\n$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)\n\n# Get the security principal for the Administrator role\n$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator\n\n# Check to see if we are currently running \"as Administrator\"\nif (-Not $myWindowsPrincipal.IsInRole($adminRole))\n{\n    Write-Output \"ERROR: You need elevated Administrator privileges in order to run this script.\"\n    Write-Output \"       Start Windows PowerShell by using the Run as Administrator option.\"\n    Exit 2\n}\n\n$EventSource = $MyInvocation.MyCommand.Name\nIf (-Not $EventSource)\n{\n    $EventSource = \"Powershell CLI\"\n}\n\nIf ([System.Diagnostics.EventLog]::Exists('Application') -eq $False -or [System.Diagnostics.EventLog]::SourceExists($EventSource) -eq $False)\n{\n    New-EventLog -LogName Application -Source $EventSource\n}\n\n# Detect PowerShell version.\nIf ($PSVersionTable.PSVersion.Major -lt 3)\n{\n    Write-Log \"PowerShell version 3 or higher is required.\"\n    Throw \"PowerShell version 3 or higher is required.\"\n}\n\n# Find and start the WinRM service.\nWrite-Verbose \"Verifying WinRM service.\"\nIf (!(Get-Service \"WinRM\"))\n{\n    Write-Log \"Unable to find the WinRM service.\"\n    Throw \"Unable to find the WinRM service.\"\n}\nElseIf ((Get-Service \"WinRM\").Status -ne \"Running\")\n{\n    Write-Verbose \"Setting WinRM service to start automatically on boot.\"\n    Set-Service -Name \"WinRM\" -StartupType Automatic\n    Write-Log \"Set WinRM service to start automatically on boot.\"\n    Write-Verbose \"Starting WinRM service.\"\n    Start-Service -Name \"WinRM\" -ErrorAction Stop\n    Write-Log \"Started WinRM service.\"\n\n}\n\n# WinRM should be running; check that we have a PS session config.\nIf (!(Get-PSSessionConfiguration -Verbose:$false) -or (!(Get-ChildItem WSMan:\\localhost\\Listener)))\n{\n  If ($SkipNetworkProfileCheck) {\n    Write-Verbose \"Enabling PS Remoting without checking Network profile.\"\n    Enable-PSRemoting -SkipNetworkProfileCheck -Force -ErrorAction Stop\n    Write-Log \"Enabled PS Remoting without checking Network profile.\"\n  }\n  Else {\n    Write-Verbose \"Enabling PS Remoting.\"\n    Enable-PSRemoting -Force -ErrorAction Stop\n    Write-Log \"Enabled PS Remoting.\"\n  }\n}\nElse\n{\n    Write-Verbose \"PS Remoting is already enabled.\"\n}\n\n# Ensure LocalAccountTokenFilterPolicy is set to 1\n# https://github.com/ansible/ansible/issues/42978\n$token_path = \"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\"\n$token_prop_name = \"LocalAccountTokenFilterPolicy\"\n$token_key = Get-Item -Path $token_path\n$token_value = $token_key.GetValue($token_prop_name, $null)\nif ($token_value -ne 1) {\n    Write-Verbose \"Setting LocalAccountTOkenFilterPolicy to 1\"\n    if ($null -ne $token_value) {\n        Remove-ItemProperty -Path $token_path -Name $token_prop_name\n    }\n    New-ItemProperty -Path $token_path -Name $token_prop_name -Value 1 -PropertyType DWORD > $null\n}\n\n# Make sure there is a SSL listener.\n$listeners = Get-ChildItem WSMan:\\localhost\\Listener\nIf (!($listeners | Where-Object {$_.Keys -like \"TRANSPORT=HTTPS\"}))\n{\n    # We cannot use New-SelfSignedCertificate on 2012R2 and earlier\n    $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays\n    Write-HostLog \"Self-signed SSL certificate generated; thumbprint: $thumbprint\"\n\n    # Create the hashtables of settings to be used.\n    $valueset = @{\n        Hostname = $SubjectName\n        CertificateThumbprint = $thumbprint\n    }\n\n    $selectorset = @{\n        Transport = \"HTTPS\"\n        Address = \"*\"\n    }\n\n    Write-Verbose \"Enabling SSL listener.\"\n    New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset\n    Write-Log \"Enabled SSL listener.\"\n}\nElse\n{\n    Write-Verbose \"SSL listener is already active.\"\n\n    # Force a new SSL cert on Listener if the $ForceNewSSLCert\n    If ($ForceNewSSLCert)\n    {\n\n        # We cannot use New-SelfSignedCertificate on 2012R2 and earlier\n        $thumbprint = New-LegacySelfSignedCert -SubjectName $SubjectName -ValidDays $CertValidityDays\n        Write-HostLog \"Self-signed SSL certificate generated; thumbprint: $thumbprint\"\n\n        $valueset = @{\n            CertificateThumbprint = $thumbprint\n            Hostname = $SubjectName\n        }\n\n        # Delete the listener for SSL\n        $selectorset = @{\n            Address = \"*\"\n            Transport = \"HTTPS\"\n        }\n        Remove-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset\n\n        # Add new Listener with new SSL cert\n        New-WSManInstance -ResourceURI 'winrm/config/Listener' -SelectorSet $selectorset -ValueSet $valueset\n    }\n}\n\n# Check for basic authentication.\n$basicAuthSetting = Get-ChildItem WSMan:\\localhost\\Service\\Auth | Where-Object {$_.Name -eq \"Basic\"}\n\nIf ($DisableBasicAuth)\n{\n    If (($basicAuthSetting.Value) -eq $true)\n    {\n        Write-Verbose \"Disabling basic auth support.\"\n        Set-Item -Path \"WSMan:\\localhost\\Service\\Auth\\Basic\" -Value $false\n        Write-Log \"Disabled basic auth support.\"\n    }\n    Else\n    {\n        Write-Verbose \"Basic auth is already disabled.\"\n    }\n}\nElse\n{\n    If (($basicAuthSetting.Value) -eq $false)\n    {\n        Write-Verbose \"Enabling basic auth support.\"\n        Set-Item -Path \"WSMan:\\localhost\\Service\\Auth\\Basic\" -Value $true\n        Write-Log \"Enabled basic auth support.\"\n    }\n    Else\n    {\n        Write-Verbose \"Basic auth is already enabled.\"\n    }\n}\n\n# If EnableCredSSP if set to true\nIf ($EnableCredSSP)\n{\n    # Check for CredSSP authentication\n    $credsspAuthSetting = Get-ChildItem WSMan:\\localhost\\Service\\Auth | Where-Object {$_.Name -eq \"CredSSP\"}\n    If (($credsspAuthSetting.Value) -eq $false)\n    {\n        Write-Verbose \"Enabling CredSSP auth support.\"\n        Enable-WSManCredSSP -role server -Force\n        Write-Log \"Enabled CredSSP auth support.\"\n    }\n}\n\nIf ($GlobalHttpFirewallAccess) {\n    Enable-GlobalHttpFirewallAccess\n}\n\n# Configure firewall to allow WinRM HTTPS connections.\n$fwtest1 = netsh advfirewall firewall show rule name=\"Allow WinRM HTTPS\"\n$fwtest2 = netsh advfirewall firewall show rule name=\"Allow WinRM HTTPS\" profile=any\nIf ($fwtest1.count -lt 5)\n{\n    Write-Verbose \"Adding firewall rule to allow WinRM HTTPS.\"\n    netsh advfirewall firewall add rule profile=any name=\"Allow WinRM HTTPS\" dir=in localport=5986 protocol=TCP action=allow\n    Write-Log \"Added firewall rule to allow WinRM HTTPS.\"\n}\nElseIf (($fwtest1.count -ge 5) -and ($fwtest2.count -lt 5))\n{\n    Write-Verbose \"Updating firewall rule to allow WinRM HTTPS for any profile.\"\n    netsh advfirewall firewall set rule name=\"Allow WinRM HTTPS\" new profile=any\n    Write-Log \"Updated firewall rule to allow WinRM HTTPS for any profile.\"\n}\nElse\n{\n    Write-Verbose \"Firewall rule already exists to allow WinRM HTTPS.\"\n}\n\n# Test a remoting connection to localhost, which should work.\n$httpResult = Invoke-Command -ComputerName \"localhost\" -ScriptBlock {$env:COMPUTERNAME} -ErrorVariable httpError -ErrorAction SilentlyContinue\n$httpsOptions = New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck\n\n$httpsResult = New-PSSession -UseSSL -ComputerName \"localhost\" -SessionOption $httpsOptions -ErrorVariable httpsError -ErrorAction SilentlyContinue\n\nIf ($httpResult -and $httpsResult)\n{\n    Write-Verbose \"HTTP: Enabled | HTTPS: Enabled\"\n}\nElseIf ($httpsResult -and !$httpResult)\n{\n    Write-Verbose \"HTTP: Disabled | HTTPS: Enabled\"\n}\nElseIf ($httpResult -and !$httpsResult)\n{\n    Write-Verbose \"HTTP: Enabled | HTTPS: Disabled\"\n}\nElse\n{\n    Write-Log \"Unable to establish an HTTP or HTTPS remoting session.\"\n    Throw \"Unable to establish an HTTP or HTTPS remoting session.\"\n}\nWrite-VerboseLog \"PS Remoting has been successfully configured for Ansible.\"\n"
  },
  {
    "path": "vagrant/Install-WMF3Hotfix.ps1",
    "content": "#Requires -Version 3.0\n<#PSScriptInfo\n.VERSION 1.0\n.GUID 6cf319d1-8c50-460b-99ee-71b11cf7270d\n.AUTHOR\n    Jordan Borean <jborean93@gmail.com>\n.COPYRIGHT\n    Jordan Borean 2017\n.TAGS\n    PowerShell,Ansible,WinRM,WMF,Hotfix\n.LICENSEURI https://github.com/jborean93/ansible-windows/blob/master/LICENSE\n.PROJECTURI https://github.com/jborean93/ansible-windows\n.RELEASENOTES\n    Version 1.0: 2017-09-27\n        Initial script created\n#>\n\n<#\n.DESCRIPTION\nThe script will install the WinRM hotfix KB2842230 which fixes the memory\nissues that occur when running over WinRM with WMF 3.0. \nThe script will;\n    1. Detect if running on PS version 3.0 and exit if it is not\n    2. Check if KB2842230 is already installed and exit if it is\n    3. Download the hotfix from Microsoft server's based on the OS version\n    4. Extract the .msu file from the downloaded hotfix\n    5. Install the .msu silently\n    6. Detect if a reboot is required and prompt whether the user wants to restart\n\nOnce the install is complete, if the install process returns an exit\ncode of 3010, it will ask the user whether to restart the computer now\nor whether it will be done later.\n\nSee https://github.com/jborean93/ansible-windows/tree/master/scripts for more\ndetails.\n.PARAMETER Verbose\n    [switch] - Whether to display Verbose logs on the console\n.EXAMPLE\n    powershell.exe -ExecutionPolicy ByPass -File Install-WMF3Hotfix.ps1\n.EXAMPLE\n    powershell.exe -ExecutionPolicy ByPass -File Install-WMF3Hotfix.ps1 -Verbose\n#>\n\n[CmdletBinding()]\nParam()\n\n$ErrorActionPreference = \"Stop\"\nif ($verbose) {\n    $VerbosePreference = \"Continue\"\n}\n\nFunction Run-Process($executable, $arguments) {\n    $process = New-Object -TypeName System.Diagnostics.Process\n    $psi = $process.StartInfo\n    $psi.FileName = $executable\n    $psi.Arguments = $arguments\n    Write-Verbose -Message \"starting new process '$executable $arguments'\"\n    $process.Start() | Out-Null\n\n    $process.WaitForExit() | Out-Null\n    $exit_code = $process.ExitCode\n    Write-Verbose -Message \"process completed with exit code '$exit_code'\"\n\n    return $exit_code\n}\n\nFunction Download-File($url, $path) {\n    Write-Verbose -Message \"downloading url '$url' to '$path'\"\n    $client = New-Object -TypeName System.Net.WebClient\n    $client.DownloadFile($url, $path)\n}\n\nFunction Extract-Zip($zip, $dest) {\n    Write-Verbose -Message \"extracting '$zip' to '$dest'\"\n    try {\n        Add-Type -AssemblyName System.IO.Compression.FileSystem > $null\n        $legacy = $false\n    } catch {\n        $legacy = $true\n    }\n\n    if ($legacy) {\n        $shell = New-Object -ComObject Shell.Application\n        $zip_src = $shell.NameSpace($zip)\n        $zip_dest = $shell.NameSpace($dest)\n        $zip_dest.CopyHere($zip_src.Items(), 1044)\n    } else {\n        [System.IO.Compression.ZipFile]::ExtractToDirectory($zip, $dest)\n    }\n}\n\n$tmp_dir = $env:temp\n$kb = \"KB2842230\"\nif ($PSVersionTable.PSVersion.Major -ne 3) {\n    Write-Verbose -Message \"$kb is only applicable with Powershell v3, no action required\"\n    exit 0\n}\n\n$hotfix_installed = Get-Hotfix -Id $kb -ErrorAction SilentlyContinue\nif ($hotfix_installed -ne $null) {\n    Write-Verbose -Message \"$kb is already installed\"\n    exit 0\n}\n\nif (-not (Test-Path -Path $tmp_dir)) {\n    New-Item -Path $tmp_dir -ItemType Directory > $null\n}\n$os_version = [Version](Get-Item -Path \"$env:SystemRoot\\System32\\kernel32.dll\").VersionInfo.ProductVersion\n$host_string = \"$($os_version.Major).$($os_version.Minor)-$($env:PROCESSOR_ARCHITECTURE)\"\nswitch($host_string) {\n    # These URLS point to the Ansible Core CI S3 bucket, MS no longer provide a link to Server 2008 so we need to\n    # rely on this URL. There are no guarantees this will stay up in the future.\n    \"6.0-x86\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/464091_intl_i386_zip.exe\"\n    }\n    \"6.0-AMD64\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/464090_intl_x64_zip.exe\"\n    }\n    \"6.1-x86\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/463983_intl_i386_zip.exe\"\n    }\n    \"6.1-AMD64\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/463984_intl_x64_zip.exe\"\n    }\n    \"6.2-x86\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/463940_intl_i386_zip.exe\"\n    }\n    \"6.2-AMD64\" {\n        $url = \"https://s3.amazonaws.com/ansible-ci-files/hotfixes/KB2842230/463941_intl_x64_zip.exe\"\n    }\n}\n\n$filename = $url.Split(\"/\")[-1]\n$compressed_file = \"$tmp_dir\\$($filename).zip\"\nDownload-File -url $url -path $compressed_file\nExtract-Zip -zip $compressed_file -dest $tmp_dir\n$file = Get-Item -Path \"$tmp_dir\\*$kb*.msu\"\nif ($file -eq $null) {\n    Write-Error -Message \"unable to find extracted msu file for hotfix KB\"\n    exit 1\n}\n\n$exit_code = Run-Process -executable $file.FullName -arguments \"/quiet /norestart\"\nif ($exit_code -eq 3010) {\n    Write-Verbose \"need to restart computer after hotfix $kb install\"\n    Restart-Computer -Confirm\n} elseif ($exit_code -ne 0) {\n    Write-Error -Message \"failed to install hotfix $($kb): exit code $exit_code\"\n} else {\n    Write-Verbose -Message \"hotfix $kb install complete\"\n}\nexit $exit_code\n"
  },
  {
    "path": "vagrant/fix_ip.ps1",
    "content": "# vmware bug to set the ip\n# see : https://github.com/hashicorp/vagrant/issues/5000#issuecomment-258209286\n\nparam ([String] $ip)\n\nnetsh.exe int ip set address Ethernet1 static $ip 255.255.255.0\n"
  }
]