diff options
Diffstat (limited to 'puppet/modules')
1000 files changed, 39593 insertions, 0 deletions
diff --git a/puppet/modules/apache/.gitignore b/puppet/modules/apache/.gitignore new file mode 100644 index 00000000..cb918d8c --- /dev/null +++ b/puppet/modules/apache/.gitignore @@ -0,0 +1,6 @@ +.tmp_*~ +.librarian +.tmp +spec/fixtures/modules +spec/fixtures/manifests +*.lock diff --git a/puppet/modules/apache/.rspec b/puppet/modules/apache/.rspec new file mode 100644 index 00000000..8c18f1ab --- /dev/null +++ b/puppet/modules/apache/.rspec @@ -0,0 +1,2 @@ +--format documentation +--color diff --git a/puppet/modules/apache/Gemfile b/puppet/modules/apache/Gemfile new file mode 100644 index 00000000..b1fc9814 --- /dev/null +++ b/puppet/modules/apache/Gemfile @@ -0,0 +1,13 @@ +source 'https://rubygems.org' + +if ENV.key?('PUPPET_VERSION') +  puppetversion = "~> #{ENV['PUPPET_VERSION']}" +else +  puppetversion = ['>= 3.3.1'] +end + +gem 'puppet', puppetversion +gem 'puppet-lint', '>=0.3.2' +gem 'puppetlabs_spec_helper', '>=0.2.0' +gem 'rake', '>=0.9.2.2' +gem 'librarian-puppet', '>=0.9.10' diff --git a/puppet/modules/apache/LICENSE b/puppet/modules/apache/LICENSE new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/puppet/modules/apache/LICENSE @@ -0,0 +1,674 @@ +                    GNU GENERAL PUBLIC LICENSE +                       Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +                            Preamble + +  The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +  The licenses for most software and other practical works are designed +to take away your freedom to share and change the works.  By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users.  We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors.  You can apply it to +your programs, too. + +  When we speak of free software, we are referring to freedom, not +price.  Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +  To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights.  Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received.  You must make sure that they, too, receive +or can get the source code.  And you must show them these terms so they +know their rights. + +  Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +  For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software.  For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +  Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so.  This is fundamentally incompatible with the aim of +protecting users' freedom to change the software.  The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable.  Therefore, we +have designed this version of the GPL to prohibit the practice for those +products.  If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + +  Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary.  To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + +  The precise terms and conditions for copying, distribution and +modification follow. + +                       TERMS AND CONDITIONS + +  0. Definitions. + +  "This License" refers to version 3 of the GNU General Public License. + +  "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +  "The Program" refers to any copyrightable work licensed under this +License.  Each licensee is addressed as "you".  "Licensees" and +"recipients" may be individuals or organizations. + +  To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy.  The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + +  A "covered work" means either the unmodified Program or a work based +on the Program. + +  To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy.  Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +  To "convey" a work means any kind of propagation that enables other +parties to make or receive copies.  Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +  An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License.  If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +  1. Source Code. + +  The "source code" for a work means the preferred form of the work +for making modifications to it.  "Object code" means any non-source +form of a work. + +  A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +  The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form.  A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +  The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities.  However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work.  For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +  The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +  The Corresponding Source for a work in source code form is that +same work. + +  2. Basic Permissions. + +  All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met.  This License explicitly affirms your unlimited +permission to run the unmodified Program.  The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work.  This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +  You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force.  You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright.  Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +  Conveying under any other circumstances is permitted solely under +the conditions stated below.  Sublicensing is not allowed; section 10 +makes it unnecessary. + +  3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +  No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +  When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +  4. Conveying Verbatim Copies. + +  You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +  You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +  5. Conveying Modified Source Versions. + +  You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +    a) The work must carry prominent notices stating that you modified +    it, and giving a relevant date. + +    b) The work must carry prominent notices stating that it is +    released under this License and any conditions added under section +    7.  This requirement modifies the requirement in section 4 to +    "keep intact all notices". + +    c) You must license the entire work, as a whole, under this +    License to anyone who comes into possession of a copy.  This +    License will therefore apply, along with any applicable section 7 +    additional terms, to the whole of the work, and all its parts, +    regardless of how they are packaged.  This License gives no +    permission to license the work in any other way, but it does not +    invalidate such permission if you have separately received it. + +    d) If the work has interactive user interfaces, each must display +    Appropriate Legal Notices; however, if the Program has interactive +    interfaces that do not display Appropriate Legal Notices, your +    work need not make them do so. + +  A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit.  Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +  6. Conveying Non-Source Forms. + +  You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +    a) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by the +    Corresponding Source fixed on a durable physical medium +    customarily used for software interchange. + +    b) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by a +    written offer, valid for at least three years and valid for as +    long as you offer spare parts or customer support for that product +    model, to give anyone who possesses the object code either (1) a +    copy of the Corresponding Source for all the software in the +    product that is covered by this License, on a durable physical +    medium customarily used for software interchange, for a price no +    more than your reasonable cost of physically performing this +    conveying of source, or (2) access to copy the +    Corresponding Source from a network server at no charge. + +    c) Convey individual copies of the object code with a copy of the +    written offer to provide the Corresponding Source.  This +    alternative is allowed only occasionally and noncommercially, and +    only if you received the object code with such an offer, in accord +    with subsection 6b. + +    d) Convey the object code by offering access from a designated +    place (gratis or for a charge), and offer equivalent access to the +    Corresponding Source in the same way through the same place at no +    further charge.  You need not require recipients to copy the +    Corresponding Source along with the object code.  If the place to +    copy the object code is a network server, the Corresponding Source +    may be on a different server (operated by you or a third party) +    that supports equivalent copying facilities, provided you maintain +    clear directions next to the object code saying where to find the +    Corresponding Source.  Regardless of what server hosts the +    Corresponding Source, you remain obligated to ensure that it is +    available for as long as needed to satisfy these requirements. + +    e) Convey the object code using peer-to-peer transmission, provided +    you inform other peers where the object code and Corresponding +    Source of the work are being offered to the general public at no +    charge under subsection 6d. + +  A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +  A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling.  In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage.  For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product.  A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +  "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source.  The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +  If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information.  But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +  The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed.  Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +  Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +  7. Additional Terms. + +  "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law.  If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +  When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it.  (Additional permissions may be written to require their own +removal in certain cases when you modify the work.)  You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +  Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +    a) Disclaiming warranty or limiting liability differently from the +    terms of sections 15 and 16 of this License; or + +    b) Requiring preservation of specified reasonable legal notices or +    author attributions in that material or in the Appropriate Legal +    Notices displayed by works containing it; or + +    c) Prohibiting misrepresentation of the origin of that material, or +    requiring that modified versions of such material be marked in +    reasonable ways as different from the original version; or + +    d) Limiting the use for publicity purposes of names of licensors or +    authors of the material; or + +    e) Declining to grant rights under trademark law for use of some +    trade names, trademarks, or service marks; or + +    f) Requiring indemnification of licensors and authors of that +    material by anyone who conveys the material (or modified versions of +    it) with contractual assumptions of liability to the recipient, for +    any liability that these contractual assumptions directly impose on +    those licensors and authors. + +  All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10.  If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term.  If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +  If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +  Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +  8. Termination. + +  You may not propagate or modify a covered work except as expressly +provided under this License.  Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +  However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +  Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +  Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License.  If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +  9. Acceptance Not Required for Having Copies. + +  You are not required to accept this License in order to receive or +run a copy of the Program.  Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance.  However, +nothing other than this License grants you permission to propagate or +modify any covered work.  These actions infringe copyright if you do +not accept this License.  Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +  10. Automatic Licensing of Downstream Recipients. + +  Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License.  You are not responsible +for enforcing compliance by third parties with this License. + +  An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations.  If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +  You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License.  For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +  11. Patents. + +  A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based.  The +work thus licensed is called the contributor's "contributor version". + +  A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version.  For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +  Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +  In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement).  To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +  If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients.  "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +  If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +  A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License.  You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +  Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +  12. No Surrender of Others' Freedom. + +  If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License.  If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all.  For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +  13. Use with the GNU Affero General Public License. + +  Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work.  The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +  14. Revised Versions of this License. + +  The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time.  Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +  Each version is given a distinguishing version number.  If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation.  If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + +  If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +  Later license versions may give you additional or different +permissions.  However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +  15. Disclaimer of Warranty. + +  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +  16. Limitation of Liability. + +  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +  17. Interpretation of Sections 15 and 16. + +  If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +                     END OF TERMS AND CONDITIONS + +            How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + +    <one line to give the program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    This program is free software: you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation, either version 3 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program.  If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + +  If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +    <program>  Copyright (C) <year>  <name of author> +    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + +  You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + +  The GNU General Public License does not permit incorporating your program +into proprietary programs.  If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library.  If this is what you want to do, use the GNU Lesser General +Public License instead of this License.  But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/puppet/modules/apache/Puppetfile b/puppet/modules/apache/Puppetfile new file mode 100644 index 00000000..86d58ae6 --- /dev/null +++ b/puppet/modules/apache/Puppetfile @@ -0,0 +1,15 @@ +# empty + +forge 'https://forgeapi.puppetlabs.com' + +mod 'shorewall', :git => 'https://git-ipuppet.immerda.ch/module-shorewall' +mod 'templatewlv', :git => 'https://git-ipuppet.immerda.ch/module-templatewlv' +mod 'mod_security', :git => 'https://git-ipuppet.immerda.ch/module-mod_security' +mod 'mod_fcgid', :git => 'https://git-ipuppet.immerda.ch/module-mod_fcgid' +mod 'php', :git => 'https://git-ipuppet.immerda.ch/module-php' +mod 'perl', :git => 'https://git-ipuppet.immerda.ch/module-perl' +mod 'scl', :git => 'https://git-ipuppet.immerda.ch/module-scl' +mod 'yum', :git => 'https://git-ipuppet.immerda.ch/module-yum' +mod 'puppetlabs-stdlib' +mod 'puppetlabs-concat' +#mod 'munin', :git => 'https://git-ipuppet.immerda.ch/module-munin' diff --git a/puppet/modules/apache/README.md b/puppet/modules/apache/README.md new file mode 100644 index 00000000..331c85b0 --- /dev/null +++ b/puppet/modules/apache/README.md @@ -0,0 +1,233 @@ +Puppet module for managing an Apache web server +=============================================== + +This module tries to manage apache on different distros in a similar manner. a +few additional directories have to be created as well some configuration files +have to be deployed to fit this schema. + +! Upgrade Notices ! + + * The $ssl_cipher_suite has been evaluated from the `cert` module in the +   past, but is now a hardcoded default for the sake of reducing dependency +   to other modules. If you were using the `cert` module before, you should +   pass this parameter when declaring the apache class ! + + * this module now only works with puppet 2.7 or newer + + * this module now uses parameterized classes, if you were using global +   variables before, you need to change the class declarations in your manifests + + * this module now requires the stdlib module + + * this module no longer requires the common module + + * if using the munin module, you need a version of the munin module that is +   at or newer than commit 77e0a70999a8c4c20ee8d9eb521b927c525ac653 (Feb 28, 2013) + + * if using munin, you will need to have the perl module installed + + * you must change your modules/site-apache to modules/site_apache + + * the $apache_no_default_site variable is no longer supported, you should +   switch to passing the parameter "no_default_site => true" to the apache class + + * the $use_munin variable is no longer supported, you should switch to +   passing the parameter 'manage_munin' to the apache class + + * the $use_shorewall variable is no longer supported, you should switch to +   passing the parameter 'manage_shorewall' to the apache class + + * if you were using apache::vhost::file, or apache::vhost::template, there is a +   wrapper called apache::vhost now that takes a $vhost_mode (either the default +   'template', or 'file), although you can continue to use the longer defines + + * Previously, apache::config::file resources would require the source to be a +   full source specification, this is no longer needed, so please change any: + +      source => "puppet:///modules/site-apache/blah" + +   to be: + +      source => "modules/site-apache/blah" + + +Requirements +------------ + + * puppet 2.7 or newer + * stdlib module + * templatewlv module + * facter >= 2.2 +   because we check for $::operatingsystemmajrelease on multiple places. +   In Debian wheezy, facter needs to get upgraded from wheezy-backports. +   The facter version of Debian jessie is new enough. + +Usage +===== + +Installing Apache +----------------- + +To install Apache, simply include the 'apache' class in your manifests: + +    include apache + +This will give you a basic managed setup. You can pass a couple parameters to the +class to have the module do some things for you: + +  * manage_shorewall: If you have the shorewall module installed and are using +    it then rules will be automatically defined for you to let traffic come from +    the exterior into the web server via port 80, and also 443 if you're using +    the apache::ssl class. (Default: false) + +  * manage_munin: If you have the munin module installed and are using it, then +    some apache graphs will be configured for you. (Default: false) + +  * no_default_site: If you do not want the 0-default.conf and +    0-default_ssl.conf virtualhosts automatically created in your node +    configuration. (Default: false) + +  * ssl: If you want to install Apache SSL support enabled, just pass this +    parameter (Default: false) + +For example: + +    class { 'apache': +      manage_shorewall => true, +      manage_munin     => true, +      no_default_site  => true, +      ssl              => true +    } + +You can install the ITK worker model to enforce stronger, per-user security: + +    include apache::itk + +On CentOS you can include 'apache::itk_plus' to get that mode. Not currently +implemented for other operating systems + +You can combine SSL support and the ITK worker model by including both classes. + + +Configuring Apache +------------------ + +To deploy a configuration files to the conf.d or include.d directory under +Apache's config directory, you can use the following: + +    apache::config::file { 'filename': +      content => 'Alias /thisApplication /usr/share/thisApplication/htdocs', +    } + +by default this will deploy a conf.d global configuration file called 'filename' +with that content. + +You can pass the parameter 'type => include' to add includes for vhosts + + +To manage users in an htpasswd file: + +    apache::htpasswd_user { "joe@$domain": +      ensure             => present,   # default: present +      site               => "$domain", # default: 'absent' - will use $name +      username           => 'joe',     # default: 'absent' - will use $name +      password           => "pass", +      password_iscrypted => false,     # default: false - will sha1 hash the value +      path               => 'absent'   # default: 'absent' - /var/www/htpasswds/${site} +    } + +This will place an encrypted version of "pass" for user joe into +/var/www/htpasswds/${site} + +You will need to make sure that ${site} exists before this is done, see the +apache::vhost class below for how this is done. + +VirtualHost files +----------------- + +vhosts can be added with the apache::vhost define. + +You can ship a flat file containing the configuration, or a template. That is +controlled by the 'vhost_mode' parameter, which can be either 'file', or +'template' (default). + +Unless specified, the source will be automatically pulled from +modules/site_apache/{templates,files}/vhosts.d, searched in this order: + +    "puppet:///modules/site_apache/vhosts.d/${::fqdn}/${name}.conf", +    "puppet:///modules/site_apache/vhosts.d/{$apache::cluster_node}/${name}.conf", +    "puppet:///modules/site_apache/vhosts.d/${::operatingsystem}.${::operatingsystemmajrelease}/${name}.conf", +    "puppet:///modules/site_apache/vhosts.d/${::operatingsystem}/${name}.conf", +    "puppet:///modules/site_apache/vhosts.d/${name}.conf", + +otherwise you can pass a 'content' parameter to configure a template location that +it should be pulled from, or a 'vhost_source' parameter to specify the file source. + +For example: + +This would deploy a the vhost for $domain, pulled from a file from the sources +listed above: + +    apache::vhost { "$domain": vhost_mode => 'file' } + +    apache::vhost { "$domain": +                       vhost_mode   => 'file', +                       vhost_source => 'modules/site_configs/vhosts.d/${name}.conf" +    } + +There are multiple other additional configurables that you can pass to each +vhost definition: + +* logmode: +   - default: Do normal logging to CustomLog and ErrorLog +   - nologs: Send every logging to /dev/null +   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +   - semianonym: Don't log ips for CustomLog, log normal ErrorLog + +* run_mode: controls in which mode the vhost should be run, there are different setups +            possible: +    - normal: (*default*) run vhost with the current active worker (default: prefork) don't +              setup anything special +    - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +           with 'proxy-itk' & 'static-itk' mode) +    - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +                 requests for the itk setup, that listens only on the loobpack device. +                 (Incompatibility: cannot be used in combination with the itk setup.) +    - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +                  content and proxies the dynamic calls to the itk setup, that listens only on +                  the loobpack device (Incompatibility: cannot be used in combination with +                  'itk' mode) + +* mod_security: Whether we use mod_security or not (will include mod_security module) +     - false: (*default*) don't activate mod_security +     - true: activate mod_security + +For templates, you can pass various parameters that will automatically configure +the template accordingly (such as php_options and php_settings). Please see +manifests/vhost/template.pp for the full list. + +There are various pre-made vhost configurations that use good defaults that you can use: + +- apache::vhost::gitweb - sets up a gitweb vhost +- apache::vhost::modperl - uses modperl, with optional fastcgi +- apache::vhost::passenger - setup passenger +- apache::vhost::proxy - setup a proxy vhost +- apache::vhost::redirect - vhost to redirect hosts +- apache::vhost::static - a static vhost +- apache::vhost::webdav - for managing webdave accessible targets + +Additionally, for php sites, there are several handy pre-made vhost configurations: + +- apache::vhost::php::drupal +- apache::vhost::php::gallery2 +- apache::vhost::php::global_exec_bin_dir +- apache::vhost::php::joomla +- apache::vhost::php::mediawiki +- apache::vhost::php::safe_mode_bin +- apache::vhost::php::silverstripe +- apache::vhost::php::simplemachine +- apache::vhost::php::spip +- apache::vhost::php::standard +- apache::vhost::php::typo3 +- apache::vhost::php::webapp +- apache::vhost::php::wordpress diff --git a/puppet/modules/apache/Rakefile b/puppet/modules/apache/Rakefile new file mode 100644 index 00000000..ec1c52b3 --- /dev/null +++ b/puppet/modules/apache/Rakefile @@ -0,0 +1,26 @@ +require 'bundler' +Bundler.require(:rake) + +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' + +Rake::Task[:lint].clear +PuppetLint::RakeTask.new :lint do |config| +  config.ignore_paths = ["spec/**/*.pp", "vendor/**/*.pp"] +  config.log_format = '%{path}:%{linenumber}:%{KIND}: %{message}' +  config.disable_checks = [ "class_inherits_from_params_class", "80chars" ] +end + +# use librarian-puppet to manage fixtures instead of .fixtures.yml +# offers more possibilities like explicit version management, forge downloads,... +task :librarian_spec_prep do +  sh "librarian-puppet install --path=spec/fixtures/modules/" +  pwd = `pwd`.strip +  unless File.directory?("#{pwd}/spec/fixtures/modules/apache") +    sh "ln -s #{pwd} #{pwd}/spec/fixtures/modules/apache" +  end +end +task :spec_prep => :librarian_spec_prep + + +task :default => [:spec, :lint] diff --git a/puppet/modules/apache/files/conf.d/CentOS/ssl.conf b/puppet/modules/apache/files/conf.d/CentOS/ssl.conf new file mode 100644 index 00000000..7f9be957 --- /dev/null +++ b/puppet/modules/apache/files/conf.d/CentOS/ssl.conf @@ -0,0 +1,76 @@ +# +# This is the Apache server configuration file providing SSL support. +# It contains the configuration directives to instruct the server how to +# serve pages over an https connection. For detailing information about these  +# directives see <URL:http://httpd.apache.org/docs/2.2/mod/mod_ssl.html> +#  +# Do NOT simply read the instructions in here without understanding +# what they do.  They're here only as hints or reminders.  If you are unsure +# consult the online docs. You have been warned.   +# + +LoadModule ssl_module modules/mod_ssl.so + +# +# When we also provide SSL we have to listen to the  +# the HTTPS port in addition. +# +Listen 443 +NameVirtualHost *:443 + +## +##  SSL Global Context +## +##  All SSL configuration in this context applies both to +##  the main server and all SSL-enabled virtual hosts. +## + +# +#   Some MIME-types for downloading Certificates and CRLs +# +AddType application/x-x509-ca-cert .crt +AddType application/x-pkcs7-crl    .crl + +#   Pass Phrase Dialog: +#   Configure the pass phrase gathering process. +#   The filtering dialog program (`builtin' is a internal +#   terminal dialog) has to provide the pass phrase on stdout. +SSLPassPhraseDialog  builtin + +#   Inter-Process Session Cache: +#   Configure the SSL Session Cache: First the mechanism  +#   to use and second the expiring timeout (in seconds). +#SSLSessionCache        dc:UNIX:/var/cache/mod_ssl/distcache +SSLSessionCache         shmcb:/var/cache/mod_ssl/scache(512000) +SSLSessionCacheTimeout  300 + +#   Semaphore: +#   Configure the path to the mutual exclusion semaphore the +#   SSL engine uses internally for inter-process synchronization.  +SSLMutex default + +#   Pseudo Random Number Generator (PRNG): +#   Configure one or more sources to seed the PRNG of the  +#   SSL library. The seed data should be of good random quality. +#   WARNING! On some platforms /dev/random blocks if not enough entropy +#   is available. This means you then cannot use the /dev/random device +#   because it would lead to very long connection times (as long as +#   it requires to make more entropy available). But usually those +#   platforms additionally provide a /dev/urandom device which doesn't +#   block. So, if available, use this one instead. Read the mod_ssl User +#   Manual for more details. +SSLRandomSeed startup file:/dev/urandom  256 +SSLRandomSeed connect builtin +#SSLRandomSeed startup file:/dev/random  512 +#SSLRandomSeed connect file:/dev/random  512 +#SSLRandomSeed connect file:/dev/urandom 512 + +# +# Use "SSLCryptoDevice" to enable any supported hardware +# accelerators. Use "openssl engine -v" to list supported +# engine names.  NOTE: If you enable an accelerator and the +# server does not start, consult the error logs and ensure +# your accelerator is functioning properly.  +# +SSLCryptoDevice builtin +#SSLCryptoDevice ubsec diff --git a/puppet/modules/apache/files/conf.d/CentOS/welcome.conf b/puppet/modules/apache/files/conf.d/CentOS/welcome.conf new file mode 100644 index 00000000..7d7b0cd6 --- /dev/null +++ b/puppet/modules/apache/files/conf.d/CentOS/welcome.conf @@ -0,0 +1,10 @@ +#  +# This configuration file enables the default "Welcome" +# page if there is no default index page present for +# the root URL.  To disable the Welcome page, comment +# out all the lines below. +# +#<LocationMatch "^/+$"> +#    Options -Indexes +#    ErrorDocument 403 /error/noindex.html +#</LocationMatch> diff --git a/puppet/modules/apache/files/conf.d/Debian/charset b/puppet/modules/apache/files/conf.d/Debian/charset new file mode 100644 index 00000000..40d7198b --- /dev/null +++ b/puppet/modules/apache/files/conf.d/Debian/charset @@ -0,0 +1,6 @@ +# Read the documentation before enabling AddDefaultCharset. +# In general, it is only a good idea if you know that all your files +# have this encoding. It will override any encoding given in the files +# in meta http-equiv or xml encoding tags. + +#AddDefaultCharset UTF-8 diff --git a/puppet/modules/apache/files/conf.d/Debian/security b/puppet/modules/apache/files/conf.d/Debian/security new file mode 100644 index 00000000..55b3e519 --- /dev/null +++ b/puppet/modules/apache/files/conf.d/Debian/security @@ -0,0 +1,50 @@ +# +# Disable access to the entire file system except for the directories that +# are explicitly allowed later. +# +# This currently breaks the configurations that come with some web application +# Debian packages. It will be made the default for the release after lenny. +# +#<Directory /> +#	AllowOverride None +#	Order Deny,Allow +#	Deny from all +#</Directory> + + +# Changing the following options will not really affect the security of the +# server, but might make attacks slightly more difficult in some cases. + +# +# ServerTokens +# This directive configures what you return as the Server HTTP response +# Header. The default is 'Full' which sends information about the OS-Type +# and compiled in modules. +# Set to one of:  Full | OS | Minimal | Minor | Major | Prod +# where Full conveys the most information, and Prod the least. +# +#ServerTokens Minimal +ServerTokens Full + +# +# Optionally add a line containing the server version and virtual host +# name to server-generated pages (internal error documents, FTP directory +# listings, mod_status and mod_info output etc., but not CGI generated +# documents or custom error documents). +# Set to "EMail" to also include a mailto: link to the ServerAdmin. +# Set to one of:  On | Off | EMail +# +#ServerSignature Off +ServerSignature On + +# +# Allow TRACE method +# +# Set to "extended" to also reflect the request body (only for testing and +# diagnostic purposes). +# +# Set to one of:  On | Off | extended +# +#TraceEnable Off +TraceEnable On + diff --git a/puppet/modules/apache/files/conf.d/Debian/ssl.conf b/puppet/modules/apache/files/conf.d/Debian/ssl.conf new file mode 100644 index 00000000..bcfe8201 --- /dev/null +++ b/puppet/modules/apache/files/conf.d/Debian/ssl.conf @@ -0,0 +1 @@ +NameVirtualHost *:443 diff --git a/puppet/modules/apache/files/conf.d/do_includes.conf b/puppet/modules/apache/files/conf.d/do_includes.conf new file mode 100644 index 00000000..f44d9d4a --- /dev/null +++ b/puppet/modules/apache/files/conf.d/do_includes.conf @@ -0,0 +1,5 @@ +# +# Add index.shtml to the list of files that will be served as directory +# indexes. +# +DirectoryIndex index.shtml diff --git a/puppet/modules/apache/files/conf.d/git.conf b/puppet/modules/apache/files/conf.d/git.conf new file mode 100644 index 00000000..c03ee2b5 --- /dev/null +++ b/puppet/modules/apache/files/conf.d/git.conf @@ -0,0 +1,5 @@ +# deny access to git repository folders +<DirectoryMatch .*\.git/.*> +    Order allow,deny +    Deny From All +</DirectoryMatch> diff --git a/puppet/modules/apache/files/conf.d/mozilla_autoconfig.conf b/puppet/modules/apache/files/conf.d/mozilla_autoconfig.conf new file mode 100644 index 00000000..6e4f7db8 --- /dev/null +++ b/puppet/modules/apache/files/conf.d/mozilla_autoconfig.conf @@ -0,0 +1,6 @@ +Alias /.well-known/autoconfig/mail/config-v1.1.xml /var/www/autoconfig/config.shtml +<Directory /var/www/autoconfig/> +  Options +Includes +  AddType application/xml .shtml +  AddOutputFilter INCLUDES .shtml +</Directory> diff --git a/puppet/modules/apache/files/conf.d/status.conf b/puppet/modules/apache/files/conf.d/status.conf new file mode 100644 index 00000000..fb706cc1 --- /dev/null +++ b/puppet/modules/apache/files/conf.d/status.conf @@ -0,0 +1,24 @@ +########################################################### +### this file is managed by PUPPET                     #### +### only modify it in puppet repo or you will          #### +### loose the changes !                                #### +########################################################### + +# Allow server status reports generated by mod_status, +# with the URL of http://servername/server-status +<Location /server-status> +    SetHandler server-status +    Order deny,allow +    Deny from all +    Allow from 127.0.0.1 + +    <IfModule mod_security2.c> +	SecRuleEngine Off +    </IfModule> +</Location> + +# ExtendedStatus controls whether Apache will generate "full" status +# information (ExtendedStatus On) or just basic information (ExtendedStatus +# Off) when the "server-status" handler is called. +ExtendedStatus On + diff --git a/puppet/modules/apache/files/conf.d/vhosts.conf b/puppet/modules/apache/files/conf.d/vhosts.conf new file mode 100644 index 00000000..86485501 --- /dev/null +++ b/puppet/modules/apache/files/conf.d/vhosts.conf @@ -0,0 +1,8 @@ +########################################################### +### this file is managed by PUPPET                     #### +### only modify it in puppet repo or you will          #### +### loose the changes !                                #### +########################################################### + +NameVirtualHost *:80 +Include vhosts.d/*.conf diff --git a/puppet/modules/apache/files/config/Debian.jessie/apache2.conf b/puppet/modules/apache/files/config/Debian.jessie/apache2.conf new file mode 100644 index 00000000..7b1f96f5 --- /dev/null +++ b/puppet/modules/apache/files/config/Debian.jessie/apache2.conf @@ -0,0 +1,221 @@ +# This is the main Apache server configuration file.  It contains the +# configuration directives that give the server its instructions. +# See http://httpd.apache.org/docs/2.4/ for detailed information about +# the directives and /usr/share/doc/apache2/README.Debian about Debian specific +# hints. +# +# +# Summary of how the Apache 2 configuration works in Debian: +# The Apache 2 web server configuration in Debian is quite different to +# upstream's suggested way to configure the web server. This is because Debian's +# default Apache2 installation attempts to make adding and removing modules, +# virtual hosts, and extra configuration directives as flexible as possible, in +# order to make automating the changes and administering the server as easy as +# possible. + +# It is split into several files forming the configuration hierarchy outlined +# below, all located in the /etc/apache2/ directory: +# +#   /etc/apache2/ +#   |-- apache2.conf +#   |   `--  ports.conf +#   |-- mods-enabled +#   |   |-- *.load +#   |   `-- *.conf +#   |-- conf-enabled +#   |   `-- *.conf +#   `-- sites-enabled +#       `-- *.conf +# +# +# * apache2.conf is the main configuration file (this file). It puts the pieces +#   together by including all remaining configuration files when starting up the +#   web server. +# +# * ports.conf is always included from the main configuration file. It is +#   supposed to determine listening ports for incoming connections which can be +#   customized anytime. +# +# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/ +#   directories contain particular configuration snippets which manage modules, +#   global configuration fragments, or virtual host configurations, +#   respectively. +# +#   They are activated by symlinking available configuration files from their +#   respective *-available/ counterparts. These should be managed by using our +#   helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See +#   their respective man pages for detailed information. +# +# * The binary is called apache2. Due to the use of environment variables, in +#   the default configuration, apache2 needs to be started/stopped with +#   /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not +#   work with the default configuration. + + +# Global configuration +# + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# NOTE!  If you intend to place this on an NFS (or otherwise network) +# mounted filesystem then please read the Mutex documentation (available +# at <URL:http://httpd.apache.org/docs/2.4/mod/core.html#mutex>); +# you will save yourself a lot of trouble. +# +# Do NOT add a slash at the end of the directory path. +# +#ServerRoot "/etc/apache2" + +# +# The accept serialization lock file MUST BE STORED ON A LOCAL DISK. +# +Mutex file:${APACHE_LOCK_DIR} default + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# This needs to be set in /etc/apache2/envvars +# +PidFile ${APACHE_PID_FILE} + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout 300 + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive On + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests 100 + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout 5 + + +# These need to be set in /etc/apache2/envvars +User ${APACHE_RUN_USER} +Group ${APACHE_RUN_GROUP} + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a <VirtualHost> +# container, error messages relating to that virtual host will be +# logged here.  If you *do* define an error logfile for a <VirtualHost> +# container, that host's errors will be logged there and not here. +# +ErrorLog ${APACHE_LOG_DIR}/error.log + +# +# LogLevel: Control the severity of messages logged to the error_log. +# Available values: trace8, ..., trace1, debug, info, notice, warn, +# error, crit, alert, emerg. +# It is also possible to configure the log level for particular modules, e.g. +# "LogLevel info ssl:warn" +# +LogLevel warn + +# Include module configuration: +IncludeOptional mods-enabled/*.load +IncludeOptional mods-enabled/*.conf + +# Include list of ports to listen on +Include ports.conf + + +# Sets the default security model of the Apache2 HTTPD server. It does +# not allow access to the root filesystem outside of /usr/share and /var/www. +# The former is used by web applications packaged in Debian, +# the latter may be used for local directories served by the web server. If +# your system is serving content from a sub-directory in /srv you must allow +# access here, or in any related virtual host. +<Directory /> +    Options FollowSymLinks +    AllowOverride None +    Require all denied +</Directory> + +<Directory /usr/share> +    AllowOverride None +    Require all granted +</Directory> + +<Directory /var/www/> +    Options Indexes FollowSymLinks +    AllowOverride None +    Require all granted +</Directory> + +#<Directory /srv/> +#   Options Indexes FollowSymLinks +#   AllowOverride None +#   Require all granted +#</Directory> + + + + +# AccessFileName: The name of the file to look for in each directory +# for additional configuration directives.  See also the AllowOverride +# directive. +# +AccessFileName .htaccess + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# +<FilesMatch "^\.ht"> +    Require all denied +</FilesMatch> + + +# +# The following directives define some format nicknames for use with +# a CustomLog directive. +# +# These deviate from the Common Log Format definitions in that they use %O +# (the actual bytes sent including headers) instead of %b (the size of the +# requested file), because the latter makes it impossible to detect partial +# requests. +# +# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended. +# Use mod_remoteip instead. +# +LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined +LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %O" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# Include of directories ignores editors' and dpkg's backup files, +# see README.Debian for details. + +# Include generic snippets of statements +IncludeOptional conf-enabled/*.conf + +# Include the virtual host configurations: +IncludeOptional sites-enabled/*.conf + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/puppet/modules/apache/files/config/Debian.wheezy/apache2.conf b/puppet/modules/apache/files/config/Debian.wheezy/apache2.conf new file mode 100644 index 00000000..50545671 --- /dev/null +++ b/puppet/modules/apache/files/config/Debian.wheezy/apache2.conf @@ -0,0 +1,268 @@ +# This is the main Apache server configuration file.  It contains the +# configuration directives that give the server its instructions. +# See http://httpd.apache.org/docs/2.2/ for detailed information about +# the directives and /usr/share/doc/apache2-common/README.Debian.gz about +# Debian specific hints. +# +# +# Summary of how the Apache 2 configuration works in Debian: +# The Apache 2 web server configuration in Debian is quite different to +# upstream's suggested way to configure the web server. This is because Debian's +# default Apache2 installation attempts to make adding and removing modules, +# virtual hosts, and extra configuration directives as flexible as possible, in +# order to make automating the changes and administering the server as easy as +# possible. + +# It is split into several files forming the configuration hierarchy outlined +# below, all located in the /etc/apache2/ directory: +# +#	/etc/apache2/ +#	|-- apache2.conf +#	|	`--  ports.conf +#	|-- mods-enabled +#	|	|-- *.load +#	|	`-- *.conf +#	|-- conf.d +#	|	`-- * +# 	`-- sites-enabled +#	 	`-- * +# +# +# * apache2.conf is the main configuration file (this file). It puts the pieces +#   together by including all remaining configuration files when starting up the +#   web server. +# +#   In order to avoid conflicts with backup files, the Include directive is +#   adapted to ignore files that: +#   - do not begin with a letter or number +#   - contain a character that is neither letter nor number nor _-:. +#   - contain .dpkg +# +#   Yet we strongly suggest that all configuration files either end with a +#   .conf or .load suffix in the file name. The next Debian release will +#   ignore files not ending with .conf (or .load for mods-enabled). +# +# * ports.conf is always included from the main configuration file. It is +#   supposed to determine listening ports for incoming connections, and which +#   of these ports are used for name based virtual hosts. +# +# * Configuration files in the mods-enabled/ and sites-enabled/ directories +#   contain particular configuration snippets which manage modules or virtual +#   host configurations, respectively. +# +#   They are activated by symlinking available configuration files from their +#   respective *-available/ counterparts. These should be managed by using our +#   helpers a2enmod/a2dismod, a2ensite/a2dissite. See +#   their respective man pages for detailed information. +# +# * Configuration files in the conf.d directory are either provided by other +#   packages or may be added by the local administrator. Local additions +#   should start with local- or end with .local.conf to avoid name clashes. All +#   files in conf.d are considered (excluding the exceptions noted above) by +#   the Apache 2 web server. +# +# * The binary is called apache2. Due to the use of environment variables, in +#   the default configuration, apache2 needs to be started/stopped with +#   /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not +#   work with the default configuration. + + +# Global configuration +# + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# NOTE!  If you intend to place this on an NFS (or otherwise network) +# mounted filesystem then please read the LockFile documentation (available +# at <URL:http://httpd.apache.org/docs/2.2/mod/mpm_common.html#lockfile>); +# you will save yourself a lot of trouble. +# +# Do NOT add a slash at the end of the directory path. +# +#ServerRoot "/etc/apache2" + +# +# The accept serialization lock file MUST BE STORED ON A LOCAL DISK. +# +LockFile ${APACHE_LOCK_DIR}/accept.lock + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# This needs to be set in /etc/apache2/envvars +# +PidFile ${APACHE_PID_FILE} + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout 300 + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive On + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests 100 + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout 5 + +## +## Server-Pool Size Regulation (MPM specific) +##  + +# prefork MPM +# StartServers: number of server processes to start +# MinSpareServers: minimum number of server processes which are kept spare +# MaxSpareServers: maximum number of server processes which are kept spare +# MaxClients: maximum number of server processes allowed to start +# MaxRequestsPerChild: maximum number of requests a server process serves +<IfModule mpm_prefork_module> +    StartServers          5 +    MinSpareServers       5 +    MaxSpareServers      10 +    MaxClients          150 +    MaxRequestsPerChild   0 +</IfModule> + +# worker MPM +# StartServers: initial number of server processes to start +# MinSpareThreads: minimum number of worker threads which are kept spare +# MaxSpareThreads: maximum number of worker threads which are kept spare +# ThreadLimit: ThreadsPerChild can be changed to this maximum value during a +#              graceful restart. ThreadLimit can only be changed by stopping +#              and starting Apache. +# ThreadsPerChild: constant number of worker threads in each server process +# MaxClients: maximum number of simultaneous client connections +# MaxRequestsPerChild: maximum number of requests a server process serves +<IfModule mpm_worker_module> +    StartServers          2 +    MinSpareThreads      25 +    MaxSpareThreads      75  +    ThreadLimit          64 +    ThreadsPerChild      25 +    MaxClients          150 +    MaxRequestsPerChild   0 +</IfModule> + +# event MPM +# StartServers: initial number of server processes to start +# MinSpareThreads: minimum number of worker threads which are kept spare +# MaxSpareThreads: maximum number of worker threads which are kept spare +# ThreadsPerChild: constant number of worker threads in each server process +# MaxClients: maximum number of simultaneous client connections +# MaxRequestsPerChild: maximum number of requests a server process serves +<IfModule mpm_event_module> +    StartServers          2 +    MinSpareThreads      25 +    MaxSpareThreads      75  +    ThreadLimit          64 +    ThreadsPerChild      25 +    MaxClients          150 +    MaxRequestsPerChild   0 +</IfModule> + +# These need to be set in /etc/apache2/envvars +User ${APACHE_RUN_USER} +Group ${APACHE_RUN_GROUP} + +# +# AccessFileName: The name of the file to look for in each directory +# for additional configuration directives.  See also the AllowOverride +# directive. +# + +AccessFileName .htaccess + +# +# The following lines prevent .htaccess and .htpasswd files from being  +# viewed by Web clients.  +# +<Files ~ "^\.ht"> +    Order allow,deny +    Deny from all +    Satisfy all +</Files> + +# +# DefaultType is the default MIME type the server will use for a document +# if it cannot otherwise determine one, such as from filename extensions. +# If your server contains mostly text or HTML documents, "text/plain" is +# a good value.  If most of your content is binary, such as applications +# or images, you may want to use "application/octet-stream" instead to +# keep browsers from trying to display binary files as though they are +# text. +# +# It is also possible to omit any default MIME type and let the +# client's browser guess an appropriate action instead. Typically the +# browser will decide based on the file's extension then. In cases +# where no good assumption can be made, letting the default MIME type +# unset is suggested  instead of forcing the browser to accept +# incorrect  metadata. +# +DefaultType None + + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a <VirtualHost> +# container, error messages relating to that virtual host will be +# logged here.  If you *do* define an error logfile for a <VirtualHost> +# container, that host's errors will be logged there and not here. +# +ErrorLog ${APACHE_LOG_DIR}/error.log + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + +# Include module configuration: +Include mods-enabled/*.load +Include mods-enabled/*.conf + +# Include list of ports to listen on and which to use for name based vhosts +Include ports.conf + +# +# The following directives define some format nicknames for use with +# a CustomLog directive (see below). +# If you are behind a reverse proxy, you might want to change %h into %{X-Forwarded-For}i +# +LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined +LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %O" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# Include of directories ignores editors' and dpkg's backup files, +# see the comments above for details. + +# Include generic snippets of statements +Include conf.d/ + +# Include the virtual host configurations: +Include sites-enabled/ diff --git a/puppet/modules/apache/files/config/Debian/apache2.conf b/puppet/modules/apache/files/config/Debian/apache2.conf new file mode 100644 index 00000000..1e97b4eb --- /dev/null +++ b/puppet/modules/apache/files/config/Debian/apache2.conf @@ -0,0 +1,230 @@ +# +# Based upon the NCSA server configuration files originally by Rob McCool. +# +# This is the main Apache server configuration file.  It contains the +# configuration directives that give the server its instructions. +# See http://httpd.apache.org/docs/2.2/ for detailed information about +# the directives. +# +# Do NOT simply read the instructions in here without understanding +# what they do.  They're here only as hints or reminders.  If you are unsure +# consult the online docs. You have been warned.   +# +# The configuration directives are grouped into three basic sections: +#  1. Directives that control the operation of the Apache server process as a +#     whole (the 'global environment'). +#  2. Directives that define the parameters of the 'main' or 'default' server, +#     which responds to requests that aren't handled by a virtual host. +#     These directives also provide default values for the settings +#     of all virtual hosts. +#  3. Settings for virtual hosts, which allow Web requests to be sent to +#     different IP addresses or hostnames and have them handled by the +#     same Apache server process. +# +# Configuration and logfile names: If the filenames you specify for many +# of the server's control files begin with "/" (or "drive:/" for Win32), the +# server will use that explicit path.  If the filenames do *not* begin +# with "/", the value of ServerRoot is prepended -- so "foo.log" +# with ServerRoot set to "/etc/apache2" will be interpreted by the +# server as "/etc/apache2/foo.log". +# + +### Section 1: Global Environment +# +# The directives in this section affect the overall operation of Apache, +# such as the number of concurrent requests it can handle or where it +# can find its configuration files. +# + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# NOTE!  If you intend to place this on an NFS (or otherwise network) +# mounted filesystem then please read the LockFile documentation (available +# at <URL:http://httpd.apache.org/docs/2.2/mod/mpm_common.html#lockfile>); +# you will save yourself a lot of trouble. +# +# Do NOT add a slash at the end of the directory path. +# +#ServerRoot "/etc/apache2" + +# +# The accept serialization lock file MUST BE STORED ON A LOCAL DISK. +# +LockFile ${APACHE_LOCK_DIR}/accept.lock + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# This needs to be set in /etc/apache2/envvars +# +PidFile ${APACHE_PID_FILE} + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout 300 + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive On + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests 100 + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout 15 + +## +## Server-Pool Size Regulation (MPM specific) +##  + +# prefork MPM +# StartServers: number of server processes to start +# MinSpareServers: minimum number of server processes which are kept spare +# MaxSpareServers: maximum number of server processes which are kept spare +# MaxClients: maximum number of server processes allowed to start +# MaxRequestsPerChild: maximum number of requests a server process serves +<IfModule mpm_prefork_module> +    StartServers          5 +    MinSpareServers       5 +    MaxSpareServers      10 +    MaxClients          150 +    MaxRequestsPerChild   0 +</IfModule> + +# worker MPM +# StartServers: initial number of server processes to start +# MaxClients: maximum number of simultaneous client connections +# MinSpareThreads: minimum number of worker threads which are kept spare +# MaxSpareThreads: maximum number of worker threads which are kept spare +# ThreadLimit: ThreadsPerChild can be changed to this maximum value during a +#              graceful restart. ThreadLimit can only be changed by stopping +#              and starting Apache. +# ThreadsPerChild: constant number of worker threads in each server process +# MaxRequestsPerChild: maximum number of requests a server process serves +<IfModule mpm_worker_module> +    StartServers          2 +    MinSpareThreads      25 +    MaxSpareThreads      75  +    ThreadLimit          64 +    ThreadsPerChild      25 +    MaxClients          150 +    MaxRequestsPerChild   0 +</IfModule> + +# event MPM +# StartServers: initial number of server processes to start +# MaxClients: maximum number of simultaneous client connections +# MinSpareThreads: minimum number of worker threads which are kept spare +# MaxSpareThreads: maximum number of worker threads which are kept spare +# ThreadsPerChild: constant number of worker threads in each server process +# MaxRequestsPerChild: maximum number of requests a server process serves +<IfModule mpm_event_module> +    StartServers          2 +    MaxClients          150 +    MinSpareThreads      25 +    MaxSpareThreads      75  +    ThreadLimit          64 +    ThreadsPerChild      25 +    MaxRequestsPerChild   0 +</IfModule> + +# These need to be set in /etc/apache2/envvars +User ${APACHE_RUN_USER} +Group ${APACHE_RUN_GROUP} + +# +# AccessFileName: The name of the file to look for in each directory +# for additional configuration directives.  See also the AllowOverride +# directive. +# + +AccessFileName .htaccess + +# +# The following lines prevent .htaccess and .htpasswd files from being  +# viewed by Web clients.  +# +<Files ~ "^\.ht"> +    Order allow,deny +    Deny from all +    Satisfy all +</Files> + +# +# DefaultType is the default MIME type the server will use for a document +# if it cannot otherwise determine one, such as from filename extensions. +# If your server contains mostly text or HTML documents, "text/plain" is +# a good value.  If most of your content is binary, such as applications +# or images, you may want to use "application/octet-stream" instead to +# keep browsers from trying to display binary files as though they are +# text. +# +DefaultType text/plain + + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a <VirtualHost> +# container, error messages relating to that virtual host will be +# logged here.  If you *do* define an error logfile for a <VirtualHost> +# container, that host's errors will be logged there and not here. +# +ErrorLog ${APACHE_LOG_DIR}/error.log + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + +# Include module configuration: +Include mods-enabled/*.load +Include mods-enabled/*.conf + +# Include all the user configurations: +Include httpd.conf + +# Include ports listing +Include ports.conf + +# +# The following directives define some format nicknames for use with +# a CustomLog directive (see below). +# If you are behind a reverse proxy, you might want to change %h into %{X-Forwarded-For}i +# +LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined +LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %O" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# Include of directories ignores editors' and dpkg's backup files, +# see README.Debian for details. + +# Include generic snippets of statements +Include conf.d/ + +# Include the virtual host configurations: +Include sites-enabled/ diff --git a/puppet/modules/apache/files/config/OpenBSD/httpd.conf b/puppet/modules/apache/files/config/OpenBSD/httpd.conf new file mode 100644 index 00000000..09e452e6 --- /dev/null +++ b/puppet/modules/apache/files/config/OpenBSD/httpd.conf @@ -0,0 +1,1120 @@ +#	$OpenBSD: httpd.conf,v 1.22 2008/01/25 09:59:57 sthen Exp $ +# +# Based upon the NCSA server configuration files originally by Rob McCool. +# +# This is the main Apache server configuration file.  It contains the +# configuration directives that give the server its instructions. +# See <URL:http://www.apache.org/docs/> for detailed information about +# the directives. +# +# Do NOT simply read the instructions in here without understanding +# what they do.  They're here only as hints or reminders.  If you are unsure +# consult the online docs. You have been warned.   +# +# After this file is processed, the server will look for and process +# /var/www/conf/srm.conf and then /var/www/conf/access.conf +# unless you have overridden these with ResourceConfig and/or +# AccessConfig directives here. +# +# The configuration directives are grouped into three basic sections: +#  1. Directives that control the operation of the Apache server process as a +#     whole (the 'global environment'). +#  2. Directives that define the parameters of the 'main' or 'default' server, +#     which responds to requests that aren't handled by a virtual host. +#     These directives also provide default values for the settings +#     of all virtual hosts. +#  3. Settings for virtual hosts, which allow Web requests to be sent to +#     different IP addresses or hostnames and have them handled by the +#     same Apache server process. +# +# Configuration and logfile names: If the filenames you specify for many +# of the server's control files begin with "/" (or "drive:/" for Win32), the +# server will use that explicit path.  If the filenames do *not* begin +# with "/", the value of ServerRoot is prepended -- so "logs/foo.log" +# with ServerRoot set to "/usr/local/apache" will be interpreted by the +# server as "/usr/local/apache/logs/foo.log". +# + +### Section 1: Global Environment +# +# The directives in this section affect the overall operation of Apache, +# such as the number of concurrent requests it can handle or where it +# can find its configuration files. +# + +# +# ServerType is either inetd, or standalone.  Inetd mode is only supported on +# Unix platforms. +# +ServerType standalone + +# +# ServerTokens is either Full, OS, Minimal, or ProductOnly. +# The values define what version information is returned in the +# Server header in HTTP responses. +# +# ServerTokens ProductOnly + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# NOTE!  If you intend to place this on an NFS (or otherwise network) +# mounted filesystem then please read the LockFile documentation +# (available at <URL:http://www.apache.org/docs/mod/core.html#lockfile>); +# you will save yourself a lot of trouble. +# +# Do NOT add a slash at the end of the directory path. +# +ServerRoot "/var/www" + +# +# The LockFile directive sets the path to the lockfile used when Apache +# is compiled with either USE_FCNTL_SERIALIZED_ACCEPT or +# USE_FLOCK_SERIALIZED_ACCEPT. This directive should normally be left at +# its default value. The main reason for changing it is if the logs +# directory is NFS mounted, since the lockfile MUST BE STORED ON A LOCAL +# DISK. The PID of the main server process is automatically appended to +# the filename.  +# +#LockFile logs/accept.lock + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# +PidFile logs/httpd.pid +# +# ScoreBoardFile: File used to store internal server process information. +# Not all architectures require this.  But if yours does (you'll know because +# this file will be  created when you run Apache) then you *must* ensure that +# no two invocations of Apache share the same scoreboard file. +# +ScoreBoardFile logs/apache_runtime_status + +# +# In the standard configuration, the server will process httpd.conf, +# srm.conf, and access.conf in that order.  The latter two files are +# now deprecated and not installed any more, as it is recommended that  +# all directives be kept in a single file for simplicity.   +# +#ResourceConfig conf/srm.conf +#AccessConfig conf/access.conf + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout 300 + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive On + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests 100 + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout 15 + +# +# Server-pool size regulation.  Rather than making you guess how many +# server processes you need, Apache dynamically adapts to the load it +# sees --- that is, it tries to maintain enough server processes to +# handle the current load, plus a few spare servers to handle transient +# load spikes (e.g., multiple simultaneous requests from a single +# Netscape browser). +# +# It does this by periodically checking how many servers are waiting +# for a request.  If there are fewer than MinSpareServers, it creates +# a new spare.  If there are more than MaxSpareServers, some of the +# spares die off.  The default values in httpd.conf-dist are probably OK +# for most sites. +# +MinSpareServers 5 +MaxSpareServers 10 + +# +# Number of servers to start initially --- should be a reasonable ballpark +# figure. +# +StartServers 5 + +# +# Limit on total number of servers running, i.e., limit on the number +# of clients who can simultaneously connect --- if this limit is ever +# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW. +# It is intended mainly as a brake to keep a runaway server from taking +# the system with it as it spirals down... +# +MaxClients 150 + +# +# MaxRequestsPerChild: the number of requests each child process is +# allowed to process before the child dies.  The child will exit so +# as to avoid problems after prolonged use when Apache (and maybe the +# libraries it uses) leak memory or other resources.  On most systems, this +# isn't really needed, but a few (such as Solaris) do have notable leaks +# in the libraries. +# +MaxRequestsPerChild 0 + +# +# MaxFOOPerChild: these directives set the current and hard rlimits for +# the child processes. Attempts to exceed them will cause the the OS to +# take appropriate action. See the setrlimit(2) and signal(3). +# +MaxCPUPerChild 0 +MaxDATAPerChild 0 +MaxNOFILEPerChild 0 +MaxRSSPerChild 0 +MaxSTACKPerChild 0 + +# +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, in addition to the default. See also the <VirtualHost> +# directive. +# +#Listen 3000 +#Listen 12.34.56.78:80 + +# +# BindAddress: You can support virtual hosts with this option. This directive +# is used to tell the server which IP address to listen to. It can either +# contain "*", an IP address, or a fully qualified Internet domain name. +# See also the <VirtualHost> and Listen directives. +# +#BindAddress * + +# +# Dynamic Shared Object (DSO) Support +# +# To be able to use the functionality of a module which was built as a DSO you +# have to place corresponding `LoadModule' lines at this location so the +# directives contained in it are actually available _before_ they are used. +# Please read the file README.DSO in the Apache 1.3 distribution for more +# details about the DSO mechanism and run `httpd -l' for the list of already +# built-in (statically linked and thus always available) modules in your httpd +# binary. +# +# Note: The order is which modules are loaded is important.  Don't change +# the order below without expert advice. +# +# Example: +# LoadModule foo_module libexec/mod_foo.so + +# "anonymous" user access to authenticated areas +# LoadModule anon_auth_module	/usr/lib/apache/modules/mod_auth_anon.so + +# user authentication using Berkeley DB files +# LoadModule db_auth_module	/usr/lib/apache/modules/mod_auth_db.so + +# user authentication using DBM files +# LoadModule dbm_auth_module	/usr/lib/apache/modules/mod_auth_dbm.so + +# authentication using new-style MD5 Digest Authentication (experimental) +# LoadModule digest_auth_module	/usr/lib/apache/modules/mod_auth_digest.so + +# CERN httpd metafile semantics +# LoadModule cern_meta_module	/usr/lib/apache/modules/mod_cern_meta.so + +# configuration defines ($xxx) +# LoadModule define_module	/usr/lib/apache/modules/mod_define.so + +# user authentication using old-style MD5 Digest Authentication +# LoadModule digest_module	/usr/lib/apache/modules/mod_digest.so + +# generation of Expires HTTP headers according to user-specified criteria +# LoadModule expires_module	/usr/lib/apache/modules/mod_expires.so + +# customization of HTTP response headers +# LoadModule headers_module	/usr/lib/apache/modules/mod_headers.so + +# comprehensive overview of the server configuration +# LoadModule info_module		/usr/lib/apache/modules/mod_info.so + +# logging of the client user agents (deprecated in favor of mod_log_config) +# LoadModule agent_log_module	/usr/lib/apache/modules/mod_log_agent.so + +# logging of referers (deprecated in favor of mod_log_config) +# LoadModule referer_log_module	/usr/lib/apache/modules/mod_log_referer.so + +# determining the MIME type of a file by looking at a few bytes of its contents +# LoadModule mime_magic_module	/usr/lib/apache/modules/mod_mime_magic.so + +# mmap()ing of a statically configured list of frequently requested but  +# not changed files (experimental) +# LoadModule mmap_static_module	/usr/lib/apache/modules/mod_mmap_static.so + +# rule-based rewriting engine to rewrite requested URLs on the fly +# LoadModule rewrite_module	/usr/lib/apache/modules/mod_rewrite.so + +# attempt to correct misspellings of URLs that users might have entered +# LoadModule speling_module	/usr/lib/apache/modules/mod_speling.so + +# provides an environment variable with a unique identifier for each request +# LoadModule unique_id_module	/usr/lib/apache/modules/mod_unique_id.so + +# uses cookies to provide for a clickstream log of user activity on a site +# LoadModule usertrack_module	/usr/lib/apache/modules/mod_usertrack.so + +# dynamically configured mass virtual hosting +# LoadModule vhost_alias_module	/usr/lib/apache/modules/mod_vhost_alias.so + +# caching proxy +# LoadModule proxy_module	/usr/lib/apache/modules/libproxy.so + +# +# Include extra module configuration files +# +Include /var/www/conf/modules/*.conf + +# +# ExtendedStatus controls whether Apache will generate "full" status +# information (ExtendedStatus On) or just basic information (ExtendedStatus +# Off) when the "server-status" handler is called. The default is Off. +# +#ExtendedStatus On + +### Section 2: 'Main' server configuration +# +# The directives in this section set up the values used by the 'main' +# server, which responds to any requests that aren't handled by a +# <VirtualHost> definition.  These values also provide defaults for +# any <VirtualHost> containers you may define later in the file. +# +# All of these directives may appear inside <VirtualHost> containers, +# in which case these default settings will be overridden for the +# virtual host being defined. +# + +# +# If your ServerType directive (set earlier in the 'Global Environment' +# section) is set to "inetd", the next few directives don't have any +# effect since their settings are defined by the inetd configuration. +# Skip ahead to the ServerAdmin directive. +# + +# +# Port: The port to which the standalone server listens. For +# ports < 1023, you will need httpd to be run as root initially. +# +Port 80 + +## +##  SSL Support +## +##  When we also provide SSL we have to listen to the  +##  standard HTTP port (see above) and to the HTTPS port +## +<IfDefine SSL> +Listen 80 +Listen 443 +</IfDefine> + +# +# If you wish httpd to run as a different user or group, you must run +# httpd as root initially and it will switch.   +# +# User/Group: The name (or #number) of the user/group to run httpd as. +#  . On SCO (ODT 3) use "User nouser" and "Group nogroup". +#  . On HPUX you may not be able to use shared memory as nobody, and the +#    suggested workaround is to create a user www and use that user. +#  NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET) +#  when the value of (unsigned)Group is above 60000;  +#  don't use Group #-1 on these systems! +#  On OpenBSD, use user www, group www. +# +User www +Group www + +# +# ServerAdmin: Your address, where problems with the server should be +# e-mailed.  This address appears on some server-generated pages, such +# as error documents. +# +ServerAdmin you@your.address + +# +# ServerName allows you to set a host name which is sent back to clients for +# your server if it's different than the one the program would get (i.e., use +# "www" instead of the host's real name). +# +# Note: You cannot just invent host names and hope they work. The name you  +# define here must be a valid DNS name for your host. If you don't understand +# this, ask your network administrator. +# If your host doesn't have a registered DNS name, enter its IP address here. +# You will have to access it by its address (e.g., http://123.45.67.89/) +# anyway, and this will make redirections work in a sensible way. +# +#ServerName new.host.name + +# +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. +# +DocumentRoot "/var/www/htdocs" + +# +# Each directory to which Apache has access, can be configured with respect +# to which services and features are allowed and/or disabled in that +# directory (and its subdirectories).  +# +# First, we configure the "default" to be a very restrictive set of  +# permissions.   +# +<Directory /> +    Options FollowSymLinks +    AllowOverride None +</Directory> + +# +# Note that from this point forward you must specifically allow +# particular features to be enabled - so if something's not working as +# you might expect, make sure that you have specifically enabled it +# below. +# + +# +# This should be changed to whatever you set DocumentRoot to. +# +<Directory "/var/www/htdocs"> + +# +# This may also be "None", "All", or any combination of "Indexes", +# "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews". +# +# Note that "MultiViews" must be named *explicitly* --- "Options All" +# doesn't give it to you. +# +    Options Indexes FollowSymLinks + +# +# This controls which options the .htaccess files in directories can +# override. Can also be "All", or any combination of "Options", "FileInfo",  +# "AuthConfig", and "Limit" +# +    AllowOverride None + +# +# Controls who can get stuff from this server. +# +    Order allow,deny +    Allow from all +</Directory> + +# +# UserDir: The directory which is prepended onto a users username, within  +# which a users's web pages are looked for if a ~user request is received.  +# Relative pathes are relative to the user's home directory. +# +# "disabled" turns this feature off. +# +# Since httpd will chroot(2) to the ServerRoot path by default, +# you should use +#	UserDir /var/www/users +# and create per user directories in /var/www/users/<username> +# + +UserDir disabled + +# +# Control access to UserDir directories.  The following is an example +# for a site where these directories are restricted to read-only and +# are located under /users/<username> +# You will need to change this to match your site's home directories. +# +#<Directory /users/*> +#    AllowOverride FileInfo AuthConfig Limit +#    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec +#    <Limit GET POST OPTIONS PROPFIND> +#        Order allow,deny +#        Allow from all +#    </Limit> +#    <Limit PUT DELETE PATCH PROPPATCH MKCOL COPY MOVE LOCK UNLOCK> +#        Order deny,allow +#        Deny from all +#    </Limit> +#</Directory> + +# +# DirectoryIndex: Name of the file or files to use as a pre-written HTML +# directory index.  Separate multiple entries with spaces. +# +DirectoryIndex index.html + +# +# AccessFileName: The name of the file to look for in each directory +# for access control information. +# +AccessFileName .htaccess + +# +# The following lines prevent .htaccess files from being viewed by +# Web clients.  Since .htaccess files often contain authorization +# information, access is disallowed for security reasons.  Comment +# these lines out if you want Web visitors to see the contents of +# .htaccess files.  If you change the AccessFileName directive above, +# be sure to make the corresponding changes here. +# +<Files .htaccess> +    Order allow,deny +    Deny from all +</Files> + +# +# CacheNegotiatedDocs: By default, Apache sends "Pragma: no-cache" with each +# document that was negotiated on the basis of content. This asks proxy +# servers not to cache the document. Uncommenting the following line disables +# this behavior, and proxies will be allowed to cache the documents. +# +#CacheNegotiatedDocs + +# +# UseCanonicalName:  (new for 1.3)  With this setting turned on, whenever +# Apache needs to construct a self-referencing URL (a URL that refers back +# to the server the response is coming from) it will use ServerName and +# Port to form a "canonical" name.  With this setting off, Apache will +# use the hostname:port that the client supplied, when possible.  This +# also affects SERVER_NAME and SERVER_PORT in CGI scripts. +# +UseCanonicalName On + +# +# TypesConfig describes where the mime.types file (or equivalent) is +# to be found. +# +TypesConfig conf/mime.types + +# +# DefaultType is the default MIME type the server will use for a document +# if it cannot otherwise determine one, such as from filename extensions. +# If your server contains mostly text or HTML documents, "text/plain" is +# a good value.  If most of your content is binary, such as applications +# or images, you may want to use "application/octet-stream" instead to +# keep browsers from trying to display binary files as though they are +# text. +# +DefaultType text/plain + +# +# The mod_mime_magic module allows the server to use various hints from the +# contents of the file itself to determine its type.  The MIMEMagicFile +# directive tells the module where the hint definitions are located. +# mod_mime_magic is not part of the default server (you have to add +# it yourself with a LoadModule [see the DSO paragraph in the 'Global +# Environment' section], or recompile the server and include mod_mime_magic +# as part of the configuration), so it's enclosed in an <IfModule> container. +# This means that the MIMEMagicFile directive will only be processed if the +# module is part of the server. +# +<IfModule mod_mime_magic.c> +    MIMEMagicFile conf/magic +</IfModule> + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a <VirtualHost> +# container, error messages relating to that virtual host will be +# logged here.  If you *do* define an error logfile for a <VirtualHost> +# container, that host's errors will be logged there and not here. +# Either a filename or the text "syslog:" followed by a facility +# name may be specified here. +# +#ErrorLog syslog:daemon +ErrorLog logs/error_log + +# +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +# +LogLevel warn + +# +# The following directives define some format nicknames for use with +# a CustomLog directive (see below). +# +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %b" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# +# The location and format of the access logfile (Common Logfile Format). +# If you do not define any access logfiles within a <VirtualHost> +# container, they will be logged here.  Contrariwise, if you *do* +# define per-<VirtualHost> access logfiles, transactions will be +# logged therein and *not* in this file. +# +CustomLog logs/access_log common + +# +# If you would like to have agent and referer logfiles, uncomment the +# following directives. +# +#CustomLog logs/referer_log referer +#CustomLog logs/agent_log agent + +# +# If you prefer a single logfile with access, agent, and referer information +# (Combined Logfile Format) you can use the following directive. +# +#CustomLog logs/access_log combined + +# +# Optionally add a line containing the server version and virtual host +# name to server-generated pages (error documents, FTP directory listings, +# mod_status and mod_info output etc., but not CGI generated documents). +# Set to "EMail" to also include a mailto: link to the ServerAdmin. +# Set to one of:  On | Off | EMail +# +# ServerSignature Off + +# +# Aliases: Add here as many aliases as you need (with no limit). The format is  +# Alias fakename realname +# +# Note that if you include a trailing / on fakename then the server will +# require it to be present in the URL.  So "/icons" isn't aliased in this +# example, only "/icons/".. +# +Alias /icons/ "/var/www/icons/" + +<Directory "/var/www/icons"> +    Options Indexes MultiViews +    AllowOverride None +    Order allow,deny +    Allow from all +</Directory> + +<Directory "/var/www/htdocs/manual"> +    Options MultiViews +    AllowOverride None +    Order allow,deny +    Allow from all +</Directory> + +# +# ScriptAlias: This controls which directories contain server scripts. +# ScriptAliases are essentially the same as Aliases, except that +# documents in the realname directory are treated as applications and +# run by the server when requested rather than as documents sent to the client. +# The same rules about trailing "/" apply to ScriptAlias directives as to +# Alias. +# +ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" + +# +# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +# +<Directory "/var/www/cgi-bin"> +    AllowOverride None +    Options None +    Order allow,deny +    Allow from all +</Directory> + +# +# Redirect allows you to tell clients about documents which used to exist in +# your server's namespace, but do not anymore. This allows you to tell the +# clients where to look for the relocated document. +# Format: Redirect old-URI new-URL +# + +# +# Directives controlling the display of server-generated directory listings. +# + +# +# FancyIndexing is whether you want fancy directory indexing or standard +# +IndexOptions FancyIndexing + +# +# AddIcon* directives tell the server which icon to show for different +# files or filename extensions.  These are only displayed for +# FancyIndexed directories. +# +AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip + +AddIconByType (TXT,/icons/text.gif) text/* +AddIconByType (IMG,/icons/image2.gif) image/* +AddIconByType (SND,/icons/sound2.gif) audio/* +AddIconByType (VID,/icons/movie.gif) video/* + +AddIcon /icons/binary.gif .bin .exe +AddIcon /icons/binhex.gif .hqx +AddIcon /icons/tar.gif .tar +AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv +AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip +AddIcon /icons/a.gif .ps .ai .eps +AddIcon /icons/layout.gif .html .shtml .htm .pdf +AddIcon /icons/text.gif .txt +AddIcon /icons/c.gif .c +AddIcon /icons/p.gif .pl .py +AddIcon /icons/f.gif .for +AddIcon /icons/dvi.gif .dvi +AddIcon /icons/uuencoded.gif .uu +AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl +AddIcon /icons/tex.gif .tex +AddIcon /icons/bomb.gif core + +AddIcon /icons/back.gif .. +AddIcon /icons/hand.right.gif README +AddIcon /icons/folder.gif ^^DIRECTORY^^ +AddIcon /icons/blank.gif ^^BLANKICON^^ + +# +# DefaultIcon is which icon to show for files which do not have an icon +# explicitly set. +# +DefaultIcon /icons/unknown.gif + +# +# AddDescription allows you to place a short description after a file in +# server-generated indexes.  These are only displayed for FancyIndexed +# directories. +# Format: AddDescription "description" filename +# +#AddDescription "GZIP compressed document" .gz +#AddDescription "tar archive" .tar +#AddDescription "GZIP compressed tar archive" .tgz + +# +# ReadmeName is the name of the README file the server will look for by +# default, and append to directory listings. +# +# HeaderName is the name of a file which should be prepended to +# directory indexes.  +# +# The server will first look for name.html and include it if found. +# If name.html doesn't exist, the server will then look for name.txt +# and include it as plaintext if found. +# +ReadmeName README +HeaderName HEADER + +# +# IndexIgnore is a set of filenames which directory indexing should ignore +# and not include in the listing.  Shell-style wildcarding is permitted. +# +IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t + +# +# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress +# information on the fly. Note: Not all browsers support this. +# Despite the name similarity, the following Add* directives have nothing +# to do with the FancyIndexing customization directives above. +# +AddEncoding x-compress Z +AddEncoding x-gzip gz + +# +# AddLanguage allows you to specify the language of a document. You can +# then use content negotiation to give a browser a file in a language +# it can understand.  Note that the suffix does not have to be the same +# as the language keyword --- those with documents in Polish (whose +# net-standard language code is pl) may wish to use "AddLanguage pl .po"  +# to avoid the ambiguity with the common suffix for perl scripts. +# +AddLanguage en .en +AddLanguage fr .fr +AddLanguage de .de +AddLanguage da .da +AddLanguage el .el +AddLanguage it .it + +# +# LanguagePriority allows you to give precedence to some languages +# in case of a tie during content negotiation. +# Just list the languages in decreasing order of preference. +# +LanguagePriority en fr de + +# +# AddType allows you to tweak mime.types without actually editing it, or to +# make certain files to be certain types. +# +# For example, the PHP module (not part of the Apache distribution) +# will typically use: +# +#AddType application/x-httpd-php .php + +# +# AddHandler allows you to map certain file extensions to "handlers", +# actions unrelated to filetype. These can be either built into the server +# or added with the Action command (see below) +# +# If you want to use server side includes, or CGI outside +# ScriptAliased directories, uncomment the following lines. +# +# To use CGI scripts: +# +#AddHandler cgi-script .cgi + +# +# To use server-parsed HTML files +# +#AddType text/html .shtml +#AddHandler server-parsed .shtml + +# +# Uncomment the following line to enable Apache's send-asis HTTP file +# feature +# +#AddHandler send-as-is asis + +# +# If you wish to use server-parsed imagemap files, use +# +#AddHandler imap-file map + +# +# To enable type maps, you might want to use +# +#AddHandler type-map var + +# +# Action lets you define media types that will execute a script whenever +# a matching file is called. This eliminates the need for repeated URL +# pathnames for oft-used CGI file processors. +# Format: Action media/type /cgi-script/location +# Format: Action handler-name /cgi-script/location +# + +# +# MetaDir: specifies the name of the directory in which Apache can find +# meta information files. These files contain additional HTTP headers +# to include when sending the document +# +#MetaDir .web + +# +# MetaSuffix: specifies the file name suffix for the file containing the +# meta information. +# +#MetaSuffix .meta + +# +# Customizable error response (Apache style) +#  these come in three flavors +# +#    1) plain text +#ErrorDocument 500 "The server made a boo boo. +#  n.b.  the (") marks it as text, it does not get output +# +#    2) local redirects +#ErrorDocument 404 /missing.html +#  to redirect to local URL /missing.html +#ErrorDocument 404 /cgi-bin/missing_handler.pl +#  N.B.: You can redirect to a script or a document using server-side-includes. +# +#    3) external redirects +#ErrorDocument 402 http://some.other_server.com/subscription_info.html +#  N.B.: Many of the environment variables associated with the original +#  request will *not* be available to such a script. + +# +# The following directives modify normal HTTP response behavior. +# The first directive disables keepalive for Netscape 2.x and browsers that +# spoof it. There are known problems with these browser implementations. +# The second directive is for Microsoft Internet Explorer 4.0b2 +# which has a broken HTTP/1.1 implementation and does not properly +# support keepalive when it is used on 301 or 302 (redirect) responses. +# +BrowserMatch "Mozilla/2" nokeepalive +BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 + +# +# The following directive disables HTTP/1.1 responses to browsers which +# are in violation of the HTTP/1.0 spec by not being able to grok a +# basic 1.1 response. +# +BrowserMatch "RealPlayer 4\.0" force-response-1.0 +BrowserMatch "Java/1\.0" force-response-1.0 +BrowserMatch "JDK/1\.0" force-response-1.0 + +# +# Allow server status reports, with the URL of http://servername/server-status +# Change the ".your_domain.com" to match your domain to enable. +# +#<Location /server-status> +#    SetHandler server-status +#    Order deny,allow +#    Deny from all +#    Allow from .your_domain.com +#</Location> + +# +# Allow remote server configuration reports, with the URL of +#  http://servername/server-info (requires that mod_info.c be loaded). +# Change the ".your_domain.com" to match your domain to enable. +# +#<Location /server-info> +#    SetHandler server-info +#    Order deny,allow +#    Deny from all +#    Allow from .your_domain.com +#</Location> + +# +# There have been reports of people trying to abuse an old bug from pre-1.1 +# days.  This bug involved a CGI script distributed as a part of Apache. +# By uncommenting these lines you can redirect these attacks to a logging  +# script on phf.apache.org.  Or, you can record them yourself, using the script +# support/phf_abuse_log.cgi. +# +#<Location /cgi-bin/phf*> +#    Deny from all +#    ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi +#</Location> + +# +# Proxy Server directives. Uncomment the following lines to +# enable the proxy server: +# +#<IfModule mod_proxy.c> +#ProxyRequests On +# +#<Directory proxy:*> +#    Order deny,allow +#    Deny from all +#    Allow from .your_domain.com +#</Directory> + +# +# Enable/disable the handling of HTTP/1.1 "Via:" headers. +# ("Full" adds the server version; "Block" removes all outgoing Via: headers) +# Set to one of: Off | On | Full | Block +# +#ProxyVia On + +# +# To enable the cache as well, edit and uncomment the following lines: +# (no cacheing without CacheRoot) +# +#CacheRoot "/var/www/proxy" +#CacheSize 5 +#CacheGcInterval 4 +#CacheMaxExpire 24 +#CacheLastModifiedFactor 0.1 +#CacheDefaultExpire 1 +#NoCache a_domain.com another_domain.edu joes.garage_sale.com + +#</IfModule> +# End of proxy directives. + +### Section 3: Virtual Hosts +# +# VirtualHost: If you want to maintain multiple domains/hostnames on your +# machine you can setup VirtualHost containers for them. +# Please see the documentation at <URL:http://www.apache.org/docs/vhosts/> +# for further details before you try to setup virtual hosts. +# You may use the command line option '-S' to verify your virtual host +# configuration. + +# +# If you want to use name-based virtual hosts you need to define at +# least one IP address (and port number) for them. +# +#NameVirtualHost 12.34.56.78:80 +#NameVirtualHost 12.34.56.78 + +# +# VirtualHost example: +# Almost any Apache directive may go into a VirtualHost container. +# +#<VirtualHost ip.address.of.host.some_domain.com> +#    ServerAdmin webmaster@host.some_domain.com +#    DocumentRoot /www/docs/host.some_domain.com +#    ServerName host.some_domain.com +#    ErrorLog logs/host.some_domain.com-error_log +#    CustomLog logs/host.some_domain.com-access_log common +#</VirtualHost> + +#<VirtualHost _default_:*> +#</VirtualHost> + + +## +##  SSL Global Context +## +##  All SSL configuration in this context applies both to +##  the main server and all SSL-enabled virtual hosts. +## + +# +#   Some MIME-types for downloading Certificates and CRLs +# +<IfDefine SSL> +AddType application/x-x509-ca-cert .crt +AddType application/x-pkcs7-crl    .crl +</IfDefine> + +<IfModule mod_ssl.c> + +#   Pass Phrase Dialog: +#   Configure the pass phrase gathering process. +#   The filtering dialog program (`builtin' is a internal +#   terminal dialog) has to provide the pass phrase on stdout. +SSLPassPhraseDialog  builtin + +#   Inter-Process Session Cache: +#   Configure the SSL Session Cache: First either `none' +#   or `dbm:/path/to/file' for the mechanism to use and +#   second the expiring timeout (in seconds). +SSLSessionCache         dbm:logs/ssl_scache +SSLSessionCacheTimeout  300 + +#   Semaphore: +#   Configure the path to the mutual exclusion semaphore the +#   SSL engine uses internally for inter-process synchronization.  +SSLMutex  sem + +#   Pseudo Random Number Generator (PRNG): +#   Configure one or more sources to seed the PRNG of the  +#   SSL library. The seed data should be of good random quality. +SSLRandomSeed startup builtin +SSLRandomSeed connect builtin +#SSLRandomSeed startup file:/dev/random  512 +#SSLRandomSeed startup file:/dev/urandom 512 +#SSLRandomSeed connect file:/dev/random  512 +#SSLRandomSeed connect file:/dev/urandom 512 +SSLRandomSeed startup file:/dev/arandom  512 + +#   Logging: +#   The home of the dedicated SSL protocol logfile. Errors are +#   additionally duplicated in the general error log file.  Put +#   this somewhere where it cannot be used for symlink attacks on +#   a real server (i.e. somewhere where only root can write). +#   Log levels are (ascending order: higher ones include lower ones): +#   none, error, warn, info, trace, debug. +SSLLog      logs/ssl_engine_log +SSLLogLevel info + +</IfModule> + +<IfDefine SSL> + +## +## SSL Virtual Host Context +## + +<VirtualHost _default_:443> + +#  General setup for the virtual host +DocumentRoot /var/www/htdocs +ServerName new.host.name +ServerAdmin you@your.address +ErrorLog logs/error_log +TransferLog logs/access_log + +#   SSL Engine Switch: +#   Enable/Disable SSL for this virtual host. +SSLEngine on + +#   SSL Cipher Suite: +#   List the ciphers that the client is permitted to negotiate. +#   See the mod_ssl documentation for a complete list. +#SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP + +#   Server Certificate: +#   Point SSLCertificateFile at a PEM encoded certificate.  If +#   the certificate is encrypted, then you will be prompted for a +#   pass phrase.  Note that a kill -HUP will prompt again. A test +#   certificate can be generated with `make certificate' under +#   built time. +SSLCertificateFile    /etc/ssl/server.crt + +#   Server Private Key: +#   If the key is not combined with the certificate, use this +#   directive to point at the key file. +SSLCertificateKeyFile /etc/ssl/private/server.key + +#   Certificate Authority (CA): +#   Set the CA certificate verification path where to find CA +#   certificates for client authentication or alternatively one +#   huge file containing all of them (file must be PEM encoded) +#   Note: Inside SSLCACertificatePath you need hash symlinks +#         to point to the certificate files. Use the provided +#         Makefile to update the hash symlinks after changes. +#SSLCACertificatePath    /var/www/conf/ssl.crt +#SSLCACertificateFile    /var/www/conf/ssl.crt/ca-bundle.crt + +#   Client Authentication (Type): +#   Client certificate verification type and depth.  Types are +#   none, optional, require and optional_no_ca.  Depth is a +#   number which specifies how deeply to verify the certificate +#   issuer chain before deciding the certificate is not valid. +#SSLVerifyClient require +#SSLVerifyDepth  10 + +#   Access Control: +#   With SSLRequire you can do per-directory access control based +#   on arbitrary complex boolean expressions containing server +#   variable checks and other lookup directives.  The syntax is a +#   mixture between C and Perl.  See the mod_ssl documentation +#   for more details. +#<Location /> +#SSLRequire (    %{SSL_CIPHER} !~ m/^(EXP|NULL)-/ \ +#            and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \ +#            and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \ +#            and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \ +#            and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20       ) \ +#           or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/ +#</Location> + +#   SSL Engine Options: +#   Set various options for the SSL engine. +#   FakeBasicAuth: +#     Translate the client X.509 into a Basic Authorisation.  This means that +#     the standard Auth/DBMAuth methods can be used for access control.  The +#     user name is the `one line' version of the client's X.509 certificate. +#     Note that no password is obtained from the user. Every entry in the user +#     file needs this password: `xxj31ZMTZzkVA'. +#   ExportCertData: +#     This exports two additional environment variables: SSL_CLIENT_CERT and +#     SSL_SERVER_CERT. These contain the PEM-encoded certificates of the +#     server (always existing) and the client (only existing when client +#     authentication is used). This can be used to import the certificates +#     into CGI scripts. +#   CompatEnvVars: +#     This exports obsolete environment variables for backward compatibility +#     to Apache-SSL 1.x, mod_ssl 2.0.x, Sioux 1.0 and Stronghold 2.x. Use this +#     to provide compatibility to existing CGI scripts. +#SSLOptions +FakeBasicAuth +ExportCertData +CompatEnvVars + +#   Per-Server Logging: +#   The home of a custom SSL log file. Use this when you want a +#   compact non-error SSL logfile on a virtual host basis. +CustomLog logs/ssl_request_log \ +          "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" + +</VirtualHost>                                   + +</IfDefine> + +# include additional things +Include conf.d/*.conf +Include vhosts.d/*.conf diff --git a/puppet/modules/apache/files/include.d/defaults.inc b/puppet/modules/apache/files/include.d/defaults.inc new file mode 100644 index 00000000..3e5e7d73 --- /dev/null +++ b/puppet/modules/apache/files/include.d/defaults.inc @@ -0,0 +1,5 @@ +RewriteEngine on +RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK) +RewriteRule .* - [F] + +ServerSignature Off diff --git a/puppet/modules/apache/files/include.d/joomla.inc b/puppet/modules/apache/files/include.d/joomla.inc new file mode 100644 index 00000000..1535ce37 --- /dev/null +++ b/puppet/modules/apache/files/include.d/joomla.inc @@ -0,0 +1,30 @@ +########## Begin - Rewrite rules to block out some common exploits +#          against joomla's +#                              +# Block out any script trying to set a mosConfig value through the URL +RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR] + +# Block out any script trying to base64_encode crap to send via URL +RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [OR] + +# Block out any script that includes a <script> tag in URL +RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR] + +# Block out any script trying to set a PHP GLOBALS variable via URL +RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR] + +# Block out any script trying to modify a _REQUEST variable via URL +RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR] + +# Block out any script that tries to set CONFIG_EXT (com_extcal2 issue) +RewriteCond %{QUERY_STRING} CONFIG_EXT(\[|\%20|\%5B).*= [NC,OR] + +# Block out any script that tries to set sbp or sb_authorname via URL (simpleboard)  +RewriteCond %{QUERY_STRING} sbp(=|\%20|\%3D) [OR] +RewriteCond %{QUERY_STRING} sb_authorname(=|\%20|\%3D) + +# Send all blocked request to homepage with 403 Forbidden error! +RewriteRule ^(.*)$ index.php [F,L] +# +########## End - Rewrite rules to block out some common exploits + diff --git a/puppet/modules/apache/files/include.d/silverstripe.inc b/puppet/modules/apache/files/include.d/silverstripe.inc new file mode 100644 index 00000000..40c44e46 --- /dev/null +++ b/puppet/modules/apache/files/include.d/silverstripe.inc @@ -0,0 +1,17 @@ +# silverstripe .htaccess +<Files *.ss> +  Order deny,allow +  Deny from all +  #Allow from 127.0.0.1 +</Files> + +<IfModule mod_rewrite.c> +  RewriteEngine On +  #RewriteBase / + +  RewriteCond %{REQUEST_URI} !(\.gif$)|(\.jpg$)|(\.png$)|(\.css$)|(\.js$) + +  RewriteCond %{REQUEST_URI} ^(.*)$ +  RewriteCond %{REQUEST_FILENAME} !-f +  RewriteRule .* sapphire/main.php?url=%1&%{QUERY_STRING} [L] +</IfModule> diff --git a/puppet/modules/apache/files/itk_plus/conf.d/CentOS/ssl.conf b/puppet/modules/apache/files/itk_plus/conf.d/CentOS/ssl.conf new file mode 100644 index 00000000..fb0c915a --- /dev/null +++ b/puppet/modules/apache/files/itk_plus/conf.d/CentOS/ssl.conf @@ -0,0 +1,75 @@ +# +# This is the Apache server configuration file providing SSL support. +# It contains the configuration directives to instruct the server how to +# serve pages over an https connection. For detailing information about these  +# directives see <URL:http://httpd.apache.org/docs/2.2/mod/mod_ssl.html> +#  +# Do NOT simply read the instructions in here without understanding +# what they do.  They're here only as hints or reminders.  If you are unsure +# consult the online docs. You have been warned.   +# + +LoadModule ssl_module modules/mod_ssl.so + +# +# When we also provide SSL we have to listen to the  +# the HTTPS port in addition. +# +NameVirtualHost *:443 + +## +##  SSL Global Context +## +##  All SSL configuration in this context applies both to +##  the main server and all SSL-enabled virtual hosts. +## + +# +#   Some MIME-types for downloading Certificates and CRLs +# +AddType application/x-x509-ca-cert .crt +AddType application/x-pkcs7-crl    .crl + +#   Pass Phrase Dialog: +#   Configure the pass phrase gathering process. +#   The filtering dialog program (`builtin' is a internal +#   terminal dialog) has to provide the pass phrase on stdout. +SSLPassPhraseDialog  builtin + +#   Inter-Process Session Cache: +#   Configure the SSL Session Cache: First the mechanism  +#   to use and second the expiring timeout (in seconds). +#SSLSessionCache        dc:UNIX:/var/cache/mod_ssl/distcache +SSLSessionCache         shmcb:/var/cache/mod_ssl/scache(512000) +SSLSessionCacheTimeout  300 + +#   Semaphore: +#   Configure the path to the mutual exclusion semaphore the +#   SSL engine uses internally for inter-process synchronization.  +SSLMutex default + +#   Pseudo Random Number Generator (PRNG): +#   Configure one or more sources to seed the PRNG of the  +#   SSL library. The seed data should be of good random quality. +#   WARNING! On some platforms /dev/random blocks if not enough entropy +#   is available. This means you then cannot use the /dev/random device +#   because it would lead to very long connection times (as long as +#   it requires to make more entropy available). But usually those +#   platforms additionally provide a /dev/urandom device which doesn't +#   block. So, if available, use this one instead. Read the mod_ssl User +#   Manual for more details. +SSLRandomSeed startup file:/dev/urandom  256 +SSLRandomSeed connect builtin +#SSLRandomSeed startup file:/dev/random  512 +#SSLRandomSeed connect file:/dev/random  512 +#SSLRandomSeed connect file:/dev/urandom 512 + +# +# Use "SSLCryptoDevice" to enable any supported hardware +# accelerators. Use "openssl engine -v" to list supported +# engine names.  NOTE: If you enable an accelerator and the +# server does not start, consult the error logs and ensure +# your accelerator is functioning properly.  +# +SSLCryptoDevice builtin +#SSLCryptoDevice ubsec diff --git a/puppet/modules/apache/files/modules.d/Gentoo/00_default_settings.conf b/puppet/modules/apache/files/modules.d/Gentoo/00_default_settings.conf new file mode 100644 index 00000000..5315fcb7 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/00_default_settings.conf @@ -0,0 +1,105 @@ +# This configuration file reflects default settings for Apache HTTP Server. +# You may change these, but chances are that you may not need to. + +# Timeout: The number of seconds before receives and sends time out. +Timeout 300 + +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +KeepAlive On + +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +MaxKeepAliveRequests 100 + +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +KeepAliveTimeout 15 + +# UseCanonicalName: Determines how Apache constructs self-referencing +# URLs and the SERVER_NAME and SERVER_PORT variables. +# When set "Off", Apache will use the Hostname and Port supplied +# by the client.  When set "On", Apache will use the value of the +# ServerName directive. +UseCanonicalName Off + +# AccessFileName: The name of the file to look for in each directory +# for additional configuration directives.  See also the AllowOverride +# directive. +AccessFileName .htaccess + +# ServerTokens +# This directive configures what you return as the Server HTTP response +# Header. The default is 'Full' which sends information about the OS-Type +# and compiled in modules. +# Set to one of:  Full | OS | Minor | Minimal | Major | Prod +# where Full conveys the most information, and Prod the least. +ServerTokens Prod + +# Optionally add a line containing the server version and virtual host +# name to server-generated pages (internal error documents, FTP directory +# listings, mod_status and mod_info output etc., but not CGI generated +# documents or custom error documents). +# Set to "EMail" to also include a mailto: link to the ServerAdmin. +# Set to one of:  On | Off | EMail +ServerSignature Off + +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +HostnameLookups Off + +# EnableMMAP and EnableSendfile: On systems that support it, +# memory-mapping or the sendfile syscall is used to deliver +# files.  This usually improves server performance, but must +# be turned off when serving from networked-mounted  +# filesystems or if support for these functions is otherwise +# broken on your system. +#EnableMMAP off +#EnableSendfile off + +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a <VirtualHost> +# container, error messages relating to that virtual host will be +# logged here.  If you *do* define an error logfile for a <VirtualHost> +# container, that host's errors will be logged there and not here. +ErrorLog /var/log/apache2/error_log + +# LogLevel: Control the number of messages logged to the error_log. +# Possible values include: debug, info, notice, warn, error, crit, +# alert, emerg. +LogLevel warn + +# We configure the "default" to be a very restrictive set of features. +<Directory /> +	Options FollowSymLinks +	AllowOverride None +	Order deny,allow +	Deny from all +</Directory> + +# DirectoryIndex: sets the file that Apache will serve if a directory +# is requested. +# +# The index.html.var file (a type-map) is used to deliver content- +# negotiated documents. The MultiViews Options can be used for the +# same purpose, but it is much slower. +# +# To add files to that list use AddDirectoryIndex in a custom config +# file. Do not change this entry unless you know what you are doing. +<IfModule dir_module> +	DirectoryIndex index.html index.html.var +</IfModule> + +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +<FilesMatch "^\.ht"> +	Order allow,deny +	Deny from all +</FilesMatch> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/00_error_documents.conf b/puppet/modules/apache/files/modules.d/Gentoo/00_error_documents.conf new file mode 100644 index 00000000..90900269 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/00_error_documents.conf @@ -0,0 +1,66 @@ +# The configuration below implements multi-language error documents through +# content-negotiation. + +# Customizable error responses come in three flavors: +# 1) plain text 2) local redirects 3) external redirects +# Some examples: +#ErrorDocument 500 "The server made a boo boo." +#ErrorDocument 404 /missing.html +#ErrorDocument 404 "/cgi-bin/missing_handler.pl" +#ErrorDocument 402 http://www.example.com/subscription_info.html + +# Required modules: mod_alias, mod_include, mod_negotiation +# We use Alias to redirect any /error/HTTP_<error>.html.var response to +# our collection of by-error message multi-language collections. We use +# includes to substitute the appropriate text. +# You can modify the messages' appearance without changing any of the +# default HTTP_<error>.html.var files by adding the line: +#   Alias /error/include/ "/your/include/path/" +# which allows you to create your own set of files by starting with the +# /var/www/localhost/error/include/ files and copying them to /your/include/path/,  +# even on a per-VirtualHost basis. The default include files will display +# your Apache version number and your ServerAdmin email address regardless +# of the setting of ServerSignature. + +<IfDefine ERRORDOCS> +<IfModule alias_module> +<IfModule mime_module> +<IfModule negotiation_module> + +Alias /error/ "/var/www/localhost/error/" + +<Directory "/var/www/localhost/error"> +	AllowOverride None +	Options IncludesNoExec +	AddOutputFilter Includes html +	AddHandler type-map var +	Order allow,deny +	Allow from all +	LanguagePriority en cs de es fr it ja ko nl pl pt-br ro sv tr +	ForceLanguagePriority Prefer Fallback +</Directory> + +ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var +ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var +ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var +ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var +ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var +ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var +ErrorDocument 410 /error/HTTP_GONE.html.var +ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var +ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var +ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var +ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var +ErrorDocument 415 /error/HTTP_UNSUPPORTED_MEDIA_TYPE.html.var +ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var +ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var +ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var +ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var +ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var + +</IfModule> +</IfModule> +</IfModule> +</IfDefine> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/00_languages.conf b/puppet/modules/apache/files/modules.d/Gentoo/00_languages.conf new file mode 100644 index 00000000..287f6544 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/00_languages.conf @@ -0,0 +1,137 @@ +# Settings for hosting different languages. +<IfDefine LANGUAGE> +<IfModule mime_module> +<IfModule negotiation_module> +# DefaultLanguage and AddLanguage allows you to specify the language of +# a document. You can then use content negotiation to give a browser a +# file in a language the user can understand. +# +# Specify a default language. This means that all data +# going out without a specific language tag (see below) will +# be marked with this one. You probably do NOT want to set +# this unless you are sure it is correct for all cases. +# +# It is generally better to not mark a page as +# being a certain language than marking it with the wrong +# language! +# +# DefaultLanguage nl +# +# Note 1: The suffix does not have to be the same as the language +# keyword --- those with documents in Polish (whose net-standard +# language code is pl) may wish to use "AddLanguage pl .po" to +# avoid the ambiguity with the common suffix for perl scripts. +# +# Note 2: The example entries below illustrate that in some cases +# the two character 'Language' abbreviation is not identical to +# the two character 'Country' code for its country, +# E.g. 'Danmark/dk' versus 'Danish/da'. +# +# Note 3: In the case of 'ltz' we violate the RFC by using a three char +# specifier. There is 'work in progress' to fix this and get +# the reference data for rfc1766 cleaned up. +# +# Catalan (ca) - Croatian (hr) - Czech (cs) - Danish (da) - Dutch (nl) +# English (en) - Esperanto (eo) - Estonian (et) - French (fr) - German (de) +# Greek-Modern (el) - Hebrew (he) - Italian (it) - Japanese (ja) +# Korean (ko) - Luxembourgeois* (ltz) - Norwegian Nynorsk (nn) +# Norwegian (no) - Polish (pl) - Portugese (pt) +# Brazilian Portuguese (pt-BR) - Russian (ru) - Swedish (sv) +# Simplified Chinese (zh-CN) - Spanish (es) - Traditional Chinese (zh-TW) +AddLanguage ca .ca +AddLanguage cs .cz .cs +AddLanguage da .dk +AddLanguage de .de +AddLanguage el .el +AddLanguage en .en +AddLanguage eo .eo +AddLanguage es .es +AddLanguage et .et +AddLanguage fr .fr +AddLanguage he .he +AddLanguage hr .hr +AddLanguage it .it +AddLanguage ja .ja +AddLanguage ko .ko +AddLanguage ltz .ltz +AddLanguage nl .nl +AddLanguage nn .nn +AddLanguage no .no +AddLanguage pl .po +AddLanguage pt .pt +AddLanguage pt-BR .pt-br +AddLanguage ru .ru +AddLanguage sv .sv +AddLanguage zh-CN .zh-cn +AddLanguage zh-TW .zh-tw + +# LanguagePriority allows you to give precedence to some languages +# in case of a tie during content negotiation. +# +# Just list the languages in decreasing order of preference. We have +# more or less alphabetized them here. You probably want to change this. +LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW + +# ForceLanguagePriority allows you to serve a result page rather than +# MULTIPLE CHOICES (Prefer) [in case of a tie] or NOT ACCEPTABLE (Fallback) +# [in case no accepted languages matched the available variants] +ForceLanguagePriority Prefer Fallback + +# Commonly used filename extensions to character sets. You probably +# want to avoid clashes with the language extensions, unless you +# are good at carefully testing your setup after each change. +# See http://www.iana.org/assignments/character-sets for the +# official list of charset names and their respective RFCs. +AddCharset us-ascii.ascii	.us-ascii +AddCharset ISO-8859-1		.iso8859-1 .latin1 +AddCharset ISO-8859-2		.iso8859-2 .latin2 .cen +AddCharset ISO-8859-3		.iso8859-3 .latin3 +AddCharset ISO-8859-4		.iso8859-4 .latin4 +AddCharset ISO-8859-5		.iso8859-5 .cyr .iso-ru +AddCharset ISO-8859-6		.iso8859-6 .arb .arabic +AddCharset ISO-8859-7		.iso8859-7 .grk .greek +AddCharset ISO-8859-8		.iso8859-8 .heb .hebrew +AddCharset ISO-8859-9		.iso8859-9 .latin5 .trk +AddCharset ISO-8859-10		.iso8859-10 .latin6 +AddCharset ISO-8859-13		.iso8859-13 +AddCharset ISO-8859-14		.iso8859-14 .latin8 +AddCharset ISO-8859-15		.iso8859-15 .latin9 +AddCharset ISO-8859-16		.iso8859-16 .latin10 +AddCharset ISO-2022-JP		.iso2022-jp .jis +AddCharset ISO-2022-KR		.iso2022-kr .kis +AddCharset ISO-2022-CN		.iso2022-cn .cis +AddCharset Big5.Big5		.big5 .b5 +AddCharset cn-Big5			.cn-big5 +# For russian, more than one charset is used (depends on client, mostly): +AddCharset WINDOWS-1251		.cp-1251 .win-1251 +AddCharset CP866			.cp866 +AddCharset KOI8				.koi8 +AddCharset KOI8-E			.koi8-e +AddCharset KOI8-r			.koi8-r .koi8-ru +AddCharset KOI8-U			.koi8-u +AddCharset KOI8-ru			.koi8-uk .ua +AddCharset ISO-10646-UCS-2	.ucs2 +AddCharset ISO-10646-UCS-4	.ucs4 +AddCharset UTF-7			.utf7 +AddCharset UTF-8			.utf8 +AddCharset UTF-16			.utf16 +AddCharset UTF-16BE			.utf16be +AddCharset UTF-16LE			.utf16le +AddCharset UTF-32			.utf32 +AddCharset UTF-32BE			.utf32be +AddCharset UTF-32LE			.utf32le +AddCharset euc-cn			.euc-cn +AddCharset euc-gb			.euc-gb +AddCharset euc-jp			.euc-jp +AddCharset euc-kr			.euc-kr +# Not sure how euc-tw got in - IANA doesn't list it??? +AddCharset EUC-TW			.euc-tw +AddCharset gb2312			.gb2312 .gb +AddCharset iso-10646-ucs-2	.ucs-2 .iso-10646-ucs-2 +AddCharset iso-10646-ucs-4	.ucs-4 .iso-10646-ucs-4 +AddCharset shift_jis		.shift_jis .sjis +</IfModule> +</IfModule> +</IfDefine> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/00_mod_autoindex.conf b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_autoindex.conf new file mode 100644 index 00000000..2512357d --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_autoindex.conf @@ -0,0 +1,83 @@ +<IfModule autoindex_module> +<IfModule alias_module> +# We include the /icons/ alias for FancyIndexed directory listings.  If +# you do not use FancyIndexing, you may comment this out. +Alias /icons/ "/var/www/localhost/icons/" + +<Directory "/var/www/localhost/icons"> +	Options Indexes MultiViews +	AllowOverride None +	Order allow,deny +	Allow from all +</Directory> +</IfModule> + +# Directives controlling the display of server-generated directory listings. +# +# To see the listing of a directory, the Options directive for the +# directory must include "Indexes", and the directory must not contain +# a file matching those listed in the DirectoryIndex directive. + +# IndexOptions: Controls the appearance of server-generated directory +# listings. +IndexOptions FancyIndexing VersionSort + +# AddIcon* directives tell the server which icon to show for different +# files or filename extensions.  These are only displayed for +# FancyIndexed directories. +AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip + +AddIconByType (TXT,/icons/text.gif) text/* +AddIconByType (IMG,/icons/image2.gif) image/* +AddIconByType (SND,/icons/sound2.gif) audio/* +AddIconByType (VID,/icons/movie.gif) video/* + +AddIcon /icons/binary.gif .bin .exe +AddIcon /icons/binhex.gif .hqx +AddIcon /icons/tar.gif .tar +AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv +AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip +AddIcon /icons/a.gif .ps .ai .eps +AddIcon /icons/layout.gif .html .shtml .htm .pdf +AddIcon /icons/text.gif .txt +AddIcon /icons/c.gif .c +AddIcon /icons/p.gif .pl .py +AddIcon /icons/f.gif .for +AddIcon /icons/dvi.gif .dvi +AddIcon /icons/uuencoded.gif .uu +AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl +AddIcon /icons/tex.gif .tex +AddIcon /icons/bomb.gif core + +AddIcon /icons/back.gif .. +AddIcon /icons/hand.right.gif README +AddIcon /icons/folder.gif ^^DIRECTORY^^ +AddIcon /icons/blank.gif ^^BLANKICON^^ + +# DefaultIcon is which icon to show for files which do not have an icon +# explicitly set. +DefaultIcon /icons/unknown.gif + +# AddDescription allows you to place a short description after a file in +# server-generated indexes.  These are only displayed for FancyIndexed +# directories. +# Format: AddDescription "description" filename + +#AddDescription "GZIP compressed document" .gz +#AddDescription "tar archive" .tar +#AddDescription "GZIP compressed tar archive" .tgz + +# ReadmeName is the name of the README file the server will look for by +# default, and append to directory listings. + +# HeaderName is the name of a file which should be prepended to  +# directory indexes.  +ReadmeName README.html +HeaderName HEADER.html + +# IndexIgnore is a set of filenames which directory indexing should ignore +# and not include in the listing.  Shell-style wildcarding is permitted. +IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t +</IfModule> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/00_mod_info.conf b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_info.conf new file mode 100644 index 00000000..53fd7aea --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_info.conf @@ -0,0 +1,14 @@ +<IfDefine INFO> +<IfModule info_module> +# Allow remote server configuration reports, with the URL of +# http://servername/server-info +<Location /server-info> +	SetHandler server-info +	Order deny,allow +	Deny from all +	Allow from 127.0.0.1 +</Location> +</IfModule> +</IfDefine> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/00_mod_log_config.conf b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_log_config.conf new file mode 100644 index 00000000..2f4244c9 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_log_config.conf @@ -0,0 +1,35 @@ +<IfModule log_config_module> +# The following directives define some format nicknames for use with +# a CustomLog directive (see below). +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %b" common + +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-Agent}i" agent +LogFormat "%v %h %l %u %t \"%r\" %>s %b %T" script +LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i VLOG=%{VLOG}e" vhost + +<IfModule logio_module> +# You need to enable mod_logio.c to use %I and %O +LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio +LogFormat "%v %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" vhostio +</IfModule> + +# The location and format of the access logfile (Common Logfile Format). +# If you do not define any access logfiles within a <VirtualHost> +# container, they will be logged here.  Contrariwise, if you *do* +# define per-<VirtualHost> access logfiles, transactions will be +# logged therein and *not* in this file. +CustomLog /var/log/apache2/access_log common + +# If you would like to have agent and referer logfiles, +# uncomment the following directives. +#CustomLog /var/log/apache2/referer_log referer +#CustomLog /var/log/apache2/agent_logs agent + +# If you prefer a logfile with access, agent, and referer information +# (Combined Logfile Format) you can use the following directive. +#CustomLog /var/log/apache2/access_log combined +</IfModule> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/00_mod_mime.conf b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_mime.conf new file mode 100644 index 00000000..51f23d55 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_mime.conf @@ -0,0 +1,55 @@ +# DefaultType: the default MIME type the server will use for a document +# if it cannot otherwise determine one, such as from filename extensions. +# If your server contains mostly text or HTML documents, "text/plain" is +# a good value.  If most of your content is binary, such as applications +# or images, you may want to use "application/octet-stream" instead to +# keep browsers from trying to display binary files as though they are +# text. +DefaultType text/plain + +<IfModule mime_module> +# TypesConfig points to the file containing the list of mappings from +# filename extension to MIME-type. +TypesConfig /etc/mime.types + +# AddType allows you to add to or override the MIME configuration +# file specified in TypesConfig for specific file types. +#AddType application/x-gzip .tgz + +# AddEncoding allows you to have certain browsers uncompress +# information on the fly. Note: Not all browsers support this. +#AddEncoding x-compress .Z +#AddEncoding x-gzip .gz .tgz + +# If the AddEncoding directives above are commented-out, then you +# probably should define those extensions to indicate media types: +AddType application/x-compress .Z +AddType application/x-gzip .gz .tgz + +# AddHandler allows you to map certain file extensions to "handlers": +# actions unrelated to filetype. These can be either built into the server +# or added with the Action directive (see below) + +# To use CGI scripts outside of ScriptAliased directories: +# (You will also need to add "ExecCGI" to the "Options" directive.) +#AddHandler cgi-script .cgi + +# For type maps (negotiated resources): +#AddHandler type-map var + +# Filters allow you to process content before it is sent to the client. +# +# To parse .shtml files for server-side includes (SSI): +# (You will also need to add "Includes" to the "Options" directive.) +#AddType text/html .shtml +#AddOutputFilter INCLUDES .shtml +</IfModule> + +<IfModule mime_magic_module> +# The mod_mime_magic module allows the server to use various hints from the +# contents of the file itself to determine its type.  The MIMEMagicFile +# directive tells the module where the hint definitions are located. +MIMEMagicFile /etc/apache2/magic +</IfModule> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/00_mod_status.conf b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_status.conf new file mode 100644 index 00000000..fa906766 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_status.conf @@ -0,0 +1,19 @@ +<IfDefine STATUS> +<IfModule status_module> +# Allow server status reports generated by mod_status, +# with the URL of http://servername/server-status +<Location /server-status> +	SetHandler server-status +	Order deny,allow +	Deny from all +	Allow from 127.0.0.1 +</Location> + +# ExtendedStatus controls whether Apache will generate "full" status +# information (ExtendedStatus On) or just basic information (ExtendedStatus +# Off) when the "server-status" handler is called. +ExtendedStatus On +</IfModule> +</IfDefine> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/00_mod_userdir.conf b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_userdir.conf new file mode 100644 index 00000000..3fb69117 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/00_mod_userdir.conf @@ -0,0 +1,40 @@ +# Settings for user home directories + +<IfDefine USERDIR> +<IfModule userdir_module> + +# UserDir: The name of the directory that is appended onto a user's home +# directory if a ~user request is received.  Note that you must also set +# the default access control for these directories, as in the example below. +UserDir public_html + +# Control access to UserDir directories.  The following is an example +# for a site where these directories are restricted to read-only. +<Directory /home/*/public_html> +	AllowOverride FileInfo AuthConfig Limit Indexes +	Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec +	<Limit GET POST OPTIONS> +		Order allow,deny +		Allow from all +	</Limit> +	<LimitExcept GET POST OPTIONS> +		Order deny,allow +		Deny from all +	</LimitExcept> +</Directory> + +# Suexec isn't really required to run cgi-scripts, but it's a really good +# idea if you have multiple users serving websites... +<IfDefine SUEXEC> +<IfModule suexec_module> +<Directory /home/*/public_html/cgi-bin> +	Options ExecCGI +	SetHandler cgi-script +</Directory> +</IfModule> +</IfDefine> + +</IfModule> +</IfDefine> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/00_mpm.conf b/puppet/modules/apache/files/modules.d/Gentoo/00_mpm.conf new file mode 100644 index 00000000..01833059 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/00_mpm.conf @@ -0,0 +1,102 @@ +# Server-Pool Management (MPM specific) + +# PidFile: The file in which the server should record its process +# identification number when it starts. +# +# Note that this is the default PidFile for most MPMs. +PidFile /var/run/apache2.pid + +# The accept serialization lock file MUST BE STORED ON A LOCAL DISK. +#LockFile /var/run/apache2.lock + +# Only one of the below sections will be relevant on your +# installed httpd.  Use "/usr/sbin/apache2 -l" to find out the +# active mpm. + +# common MPM configuration +# These configuration directives apply to all MPMs +# +# StartServers: Number of child server processes created at startup +# MaxClients: Maximum number of child processes to serve requests +# MaxRequestsPerChild: Limit on the number of requests that an individual child +#                      server will handle during its life + + +# prefork MPM +# This is the default MPM if USE=-threads +# +# MinSpareServers: Minimum number of idle child server processes +# MaxSpareServers: Maximum number of idle child server processes +<IfModule mpm_prefork_module> +	StartServers		5 +	MinSpareServers		5 +	MaxSpareServers		10 +	MaxClients			150 +	MaxRequestsPerChild	10000 +</IfModule> + +# worker MPM +# This is the default MPM if USE=threads +# +# MinSpareThreads: Minimum number of idle threads available to handle request spikes +# MaxSpareThreads: Maximum number of idle threads +# ThreadsPerChild: Number of threads created by each child process +<IfModule mpm_worker_module> +	StartServers		2 +	MinSpareThreads		25 +	MaxSpareThreads		75 +	ThreadsPerChild		25 +	MaxClients			150 +	MaxRequestsPerChild	10000 +</IfModule> + +# event MPM +# +# MinSpareThreads: Minimum number of idle threads available to handle request spikes +# MaxSpareThreads: Maximum number of idle threads +# ThreadsPerChild: Number of threads created by each child process +<IfModule mpm_event_module> +	StartServers		2 +	MinSpareThreads		25 +	MaxSpareThreads		75 +	ThreadsPerChild		25 +	MaxClients			150 +	MaxRequestsPerChild	10000 +</IfModule> + +# peruser MPM +# +# MinSpareProcessors: Minimum number of idle child server processes +# MinProcessors: Minimum number of processors per virtual host +# MaxProcessors: Maximum number of processors per virtual host +# ExpireTimeout: Maximum idle time before a child is killed, 0 to disable +# Multiplexer: Specify a Multiplexer child configuration. +# Processor: Specify a user and group for a specific child process +<IfModule mpm_peruser_module> +	MinSpareProcessors	2 +	MinProcessors		2 +	MaxProcessors		10 +	MaxClients			150 +	MaxRequestsPerChild	1000 +	ExpireTimeout		1800 + +	# KeepAlive *MUST* be set to off +	KeepAlive Off + +	Multiplexer nobody nobody +	Processor apache apache +</IfModule> + +# itk MPM +# +# MinSpareServers: Minimum number of idle child server processes +# MaxSpareServers: Maximum number of idle child server processes +<IfModule mpm_itk_module> +	StartServers		5 +	MinSpareServers		5 +	MaxSpareServers		10 +	MaxClients			150 +	MaxRequestsPerChild	10000 +</IfModule> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/10_mod_mem_cache.conf b/puppet/modules/apache/files/modules.d/Gentoo/10_mod_mem_cache.conf new file mode 100644 index 00000000..ad7fa9e0 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/10_mod_mem_cache.conf @@ -0,0 +1,10 @@ +<IfDefine MEM_CACHE> +# 128MB cache for objects < 2MB +CacheEnable mem / +MCacheSize 131072 +MCacheMaxObjectCount 1000 +MCacheMinObjectSize 1 +MCacheMaxObjectSize 2048 +</IfDefine> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/40_mod_ssl.conf b/puppet/modules/apache/files/modules.d/Gentoo/40_mod_ssl.conf new file mode 100644 index 00000000..331783a6 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/40_mod_ssl.conf @@ -0,0 +1,65 @@ +# Note: The following must must be present to support +# starting without SSL on platforms with no /dev/random equivalent +# but a statically compiled-in mod_ssl. +<IfModule ssl_module> +SSLRandomSeed startup builtin +SSLRandomSeed connect builtin +</IfModule> + +<IfDefine SSL> +<IfModule ssl_module> +# This is the Apache server configuration file providing SSL support. +# It contains the configuration directives to instruct the server how to +# serve pages over an https connection. For detailing information about these  +# directives see <URL:http://httpd.apache.org/docs/2.2/mod/mod_ssl.html> + +# Do NOT simply read the instructions in here without understanding +# what they do.  They're here only as hints or reminders. If you are unsure +# consult the online docs. You have been warned. + +## Pseudo Random Number Generator (PRNG): +# Configure one or more sources to seed the PRNG of the SSL library. +# The seed data should be of good random quality. +# WARNING! On some platforms /dev/random blocks if not enough entropy +# is available. This means you then cannot use the /dev/random device +# because it would lead to very long connection times (as long as +# it requires to make more entropy available). But usually those +# platforms additionally provide a /dev/urandom device which doesn't +# block. So, if available, use this one instead. Read the mod_ssl User +# Manual for more details. +#SSLRandomSeed startup file:/dev/random  512 +#SSLRandomSeed startup file:/dev/urandom 512 +#SSLRandomSeed connect file:/dev/random  512 +#SSLRandomSeed connect file:/dev/urandom 512 + +## SSL Global Context: +# All SSL configuration in this context applies both to the main server and  +# all SSL-enabled virtual hosts. + +# Some MIME-types for downloading Certificates and CRLs +<IfModule mime_module> +	AddType application/x-x509-ca-cert .crt +	AddType application/x-pkcs7-crl    .crl +</IfModule> + +## Pass Phrase Dialog: +# Configure the pass phrase gathering process. The filtering dialog program  +# (`builtin' is a internal terminal dialog) has to provide the pass phrase on +# stdout. +SSLPassPhraseDialog  builtin + +## Inter-Process Session Cache: +# Configure the SSL Session Cache: First the mechanism  to use and second the +# expiring timeout (in seconds). +#SSLSessionCache		dbm:/var/run/ssl_scache +SSLSessionCache			shmcb:/var/run/ssl_scache(512000) +SSLSessionCacheTimeout  300 + +## Semaphore: +# Configure the path to the mutual exclusion semaphore the SSL engine uses +# internally for inter-process synchronization. +SSLMutex  file:/var/run/ssl_mutex +</IfModule> +</IfDefine> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/45_mod_dav.conf b/puppet/modules/apache/files/modules.d/Gentoo/45_mod_dav.conf new file mode 100644 index 00000000..b15ca017 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/45_mod_dav.conf @@ -0,0 +1,56 @@ +<IfDefine DAV> +<IfModule dav_module> +<IfModule dav_fs_module> +DavLockDB "/var/lib/dav/lockdb" + +# The following example gives DAV write access to a directory called +# "uploads" under the ServerRoot directory. +<IfModule alias_module> +<IfModule auth_digest_module> +<IfModule authn_file_module> +Alias /uploads "/var/www/uploads" + +<Directory "/var/www/uploads"> +	Dav On + +	AuthType Digest +	AuthName DAV-upload + +	# You can use the htdigest program to create the password database: +	#   htdigest -c "/var/www/.htpasswd-dav" DAV-upload admin +	AuthUserFile "/var/www/.htpasswd-dav" + +	# Allow access from any host +	Order allow,deny +	Allow from all + +	# Allow universal read-access, but writes are restricted +	# to the admin user. +	<LimitExcept GET OPTIONS> +		require user admin +	</LimitExcept> +</Directory> +</IfModule> +</IfModule> +</IfModule> + +</IfModule> +</IfModule> + +# The following directives disable redirects on non-GET requests for +# a directory that does not include the trailing slash.  This fixes a  +# problem with several clients that do not appropriately handle  +# redirects for folders with DAV methods. +<IfModule setenvif_module> +BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully +BrowserMatch "MS FrontPage" redirect-carefully +BrowserMatch "^WebDrive" redirect-carefully +BrowserMatch "^WebDAVFS/1.[012345]" redirect-carefully +BrowserMatch "^gnome-vfs/1.0" redirect-carefully +BrowserMatch "^XML Spy" redirect-carefully +BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully +</IfModule> + +</IfDefine> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/46_mod_ldap.conf b/puppet/modules/apache/files/modules.d/Gentoo/46_mod_ldap.conf new file mode 100644 index 00000000..837bc6e6 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/46_mod_ldap.conf @@ -0,0 +1,29 @@ +# Examples below are taken from the online documentation +# Refer to: +# http://localhost/manual/mod/mod_ldap.html +# http://localhost/manual/mod/mod_auth_ldap.html +<IfDefine LDAP> +<IfModule ldap_module> +LDAPSharedCacheSize	200000 +LDAPCacheEntries	1024 +LDAPCacheTTL		600 +LDAPOpCacheEntries	1024 +LDAPOpCacheTTL		600 + +<Location /ldap-status> +	SetHandler ldap-status +	Order deny,allow +	Deny from all +	Allow from 127.0.0.1 +</Location> +</IfModule> +</IfDefine> + +<IfDefine AUTHNZ_LDAP> +<IfModule authnz_ldap_module> +	#AuthLDAPURL ldap://ldap1.airius.com:389/ou=People, o=Airius?uid?sub?(objectClass=*) +	#require valid-user +</IfModule> +</IfDefine> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/modules.d/Gentoo/70_mod_php5.conf b/puppet/modules/apache/files/modules.d/Gentoo/70_mod_php5.conf new file mode 100644 index 00000000..a8254359 --- /dev/null +++ b/puppet/modules/apache/files/modules.d/Gentoo/70_mod_php5.conf @@ -0,0 +1,18 @@ +<IfDefine PHP5> +	# Load the module first +	<IfModule !mod_php5.c> +		LoadModule php5_module    modules/libphp5.so +	</IfModule> + +	# Set it to handle the files +	<IfModule mod_mime.c> +		AddType application/x-httpd-php .php +		AddType application/x-httpd-php .phtml +		AddType application/x-httpd-php .php3 +		AddType application/x-httpd-php .php4 +		AddType application/x-httpd-php .php5 +		AddType application/x-httpd-php-source .phps +	</IfModule> + +	DirectoryIndex index.php index.phtml +</IfDefine> diff --git a/puppet/modules/apache/files/munin/apache_activity b/puppet/modules/apache/files/munin/apache_activity new file mode 100755 index 00000000..65fc0722 --- /dev/null +++ b/puppet/modules/apache/files/munin/apache_activity @@ -0,0 +1,99 @@ +#!/usr/bin/perl +# +# Parameters supported: +# +# 	config +# 	autoconf +# +# Configurable variables +# +# 	url      - Override default status-url +# +# Magic markers: +#%# family=auto +#%# capabilities=autoconf + +my $ret = undef; +if (!eval "require LWP::UserAgent;") { +    $ret = "LWP::UserAgent not found"; +} + +my $URL = exists $ENV{'url'} ? $ENV{'url'} : "http://127.0.0.1:%d/server-status?auto"; +my @PORTS = exists $ENV{'ports'} ? split(' ', $ENV{'ports'}) : (80); +my %chars = ( +	     # '\_' => 'Waiting', +	     # 'S' => 'Starting up', +	     'R' => 'Reading request', +	     'W' => 'Sending reply', +	     'K' => 'Keepalive', +	     'D' => 'DNS lookup', +	     'C' => 'Closing', +	     # 'L' => 'Logging', +	     # 'G' => 'Gracefully finishing', +	     # 'I' => 'Idle cleanup', +	     # '\.' => 'Open slot', +	     ); + +#    "_" Waiting for Connection, "S" Starting up, "R" Reading Request, +#    "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup, +#    "C" Closing connection, "L" Logging, "G" Gracefully finishing, +#    "I" Idle cleanup of worker, "." Open slot with no current process + +if (exists $ARGV[0] and $ARGV[0] eq "autoconf") { +    if ($ret) { +	print "no ($ret)\n"; +	exit 1; +    } +    my $ua = LWP::UserAgent->new(timeout => 30); +    my @badports; +     +    foreach my $port (@PORTS) { +	my $url = sprintf $URL, $port; +	my $response = $ua->request(HTTP::Request->new('GET',$url)); +	push @badports, $port unless $response->is_success and $response->content =~ /Scoreboard/im; +    } +     +    if (@badports) { +	print "no (no apache server-status on ports @badports)\n"; +	exit 1; +    } else { +	print "yes\n"; +	exit 0; +    } +} + +if (exists $ARGV[0] and $ARGV[0] eq "config") { +    print "graph_title Apache activity\n"; +    print "graph_args --base 1000 -l 0\n"; +    print "graph_category apache\n"; +    print "graph_vlabel processes\n"; +    foreach my $port (@PORTS) { +	while (my ($char, $val) = each (%chars)) { +	    $char =~ s/\\\./dot/; +            $char =~ s/\\\_/underline/; +            print "activity_${port}_${char}.label "; +	    print $val, "\n"; +            print "activity_${port}_${char}.type GAUGE\n"; +        } +    }     +    exit 0; +} + +foreach my $port (@PORTS) { +    my $ua = LWP::UserAgent->new (timeout => 30); +    my $url = sprintf $URL, $port; +    my $response = $ua->request (HTTP::Request->new('GET',$url)); +    if ($response->content =~ /^Scoreboard\:\s?(.*)$/sm) { +	my $string = $1; +	chomp $string; +	my @act = split (//, $string); +	foreach my $char (keys (%chars)) { +	    my $num = scalar (grep (/$char/, @act)); +	    $char =~ s/\\\./dot/; +	    $char =~ s/\\\_/underline/; +	    print "activity_${port}_${char}.value $num\n"; +	} +    } +} + + diff --git a/puppet/modules/apache/files/scripts/OpenBSD/bin/apache_logrotate.sh b/puppet/modules/apache/files/scripts/OpenBSD/bin/apache_logrotate.sh new file mode 100644 index 00000000..c2fcad97 --- /dev/null +++ b/puppet/modules/apache/files/scripts/OpenBSD/bin/apache_logrotate.sh @@ -0,0 +1,7 @@ +#!/bin/sh +WEBROOT="/var/www/htdocs" +#PIDFILE="/var/www/logs/httpd.pid" +echo "#Autogenrated newsyslog.conf\n# logfile_name          owner:group     mode count size when  flags" +find /var/www/logs -name '*_log' -exec perl -e 'print "\n{}\twww:www\t644\t30\t*\t\$D0\tZ" ' \; +find $WEBROOT -name '*_log' -exec perl -e 'print "\n{}\twww:www\t644\t30\t*\t\$D0\tZ" ' \; +perl -e 'print "\t\t \"/bin/sh /opt/bin/restart_apache.sh\"";' diff --git a/puppet/modules/apache/files/scripts/OpenBSD/bin/restart_apache.sh b/puppet/modules/apache/files/scripts/OpenBSD/bin/restart_apache.sh new file mode 100644 index 00000000..4dc936d3 --- /dev/null +++ b/puppet/modules/apache/files/scripts/OpenBSD/bin/restart_apache.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +ignoreout='Processing config' +apachectl restart 2>&1 | (egrep -v -e "_default_ VirtualHost overlap on port 443" -e "$ignoreout" -e "/usr/sbin/apachectl restart: httpd restarted" || true ) +sleep 10 +apachectl start 2>&1 | (egrep -v -e "_default_ VirtualHost overlap on port 443" -e "$ignoreout" -e "/usr/sbin/apachectl startssl: httpd started" || true ) diff --git a/puppet/modules/apache/files/scripts/OpenBSD/bin/restart_apache_ssl.sh b/puppet/modules/apache/files/scripts/OpenBSD/bin/restart_apache_ssl.sh new file mode 100644 index 00000000..314018b6 --- /dev/null +++ b/puppet/modules/apache/files/scripts/OpenBSD/bin/restart_apache_ssl.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +ignoreout='Processing config' +apachectl restart 2>&1 | (egrep -v -e "_default_ VirtualHost overlap on port 443" -e "$ignoreout" -e "/usr/sbin/apachectl restart: httpd restarted" || true ) +sleep 10 +apachectl startssl 2>&1 | (egrep -v -e "_default_ VirtualHost overlap on port 443" -e "$ignoreout" -e "/usr/sbin/apachectl startssl: httpd started" || true ) diff --git a/puppet/modules/apache/files/service/CentOS/httpd b/puppet/modules/apache/files/service/CentOS/httpd new file mode 100644 index 00000000..7102c611 --- /dev/null +++ b/puppet/modules/apache/files/service/CentOS/httpd @@ -0,0 +1,22 @@ +# Configuration file for the httpd service. + +# +# The default processing model (MPM) is the process-based +# 'prefork' model.  A thread-based model, 'worker', is also +# available, but does not work with some modules (such as PHP). +# The service must be stopped before changing this variable. +# +#HTTPD=/usr/sbin/httpd.worker + +# +# To pass additional options (for instance, -D definitions) to the +# httpd binary at startup, set OPTIONS here. +# +#OPTIONS= + +# +# By default, the httpd process is started in the C locale; to  +# change the locale in which the server runs, the HTTPD_LANG +# variable can be set. +# +#HTTPD_LANG=C diff --git a/puppet/modules/apache/files/service/CentOS/httpd.itk b/puppet/modules/apache/files/service/CentOS/httpd.itk new file mode 100644 index 00000000..62a2d24f --- /dev/null +++ b/puppet/modules/apache/files/service/CentOS/httpd.itk @@ -0,0 +1,23 @@ +# Configuration file for the httpd service. + +# +# The default processing model (MPM) is the process-based +# 'prefork' model.  A thread-based model, 'worker', is also +# available, but does not work with some modules (such as PHP). +# The service must be stopped before changing this variable. +# +#HTTPD=/usr/sbin/httpd.worker +HTTPD=/usr/sbin/httpd.itk + +# +# To pass additional options (for instance, -D definitions) to the +# httpd binary at startup, set OPTIONS here. +# +#OPTIONS= + +# +# By default, the httpd process is started in the C locale; to  +# change the locale in which the server runs, the HTTPD_LANG +# variable can be set. +# +#HTTPD_LANG=C diff --git a/puppet/modules/apache/files/service/CentOS/httpd.itk_plus b/puppet/modules/apache/files/service/CentOS/httpd.itk_plus new file mode 100644 index 00000000..4d74de2c --- /dev/null +++ b/puppet/modules/apache/files/service/CentOS/httpd.itk_plus @@ -0,0 +1,24 @@ +# Configuration file for the httpd service. + +# +# The default processing model (MPM) is the process-based +# 'prefork' model.  A thread-based model, 'worker', is also +# available, but does not work with some modules (such as PHP). +# The service must be stopped before changing this variable. +# +#HTTPD=/usr/sbin/httpd.worker +HTTPD=/usr/sbin/httpd +HTTPD_LOCAL=/usr/sbin/httpd.itk + +# +# To pass additional options (for instance, -D definitions) to the +# httpd binary at startup, set OPTIONS here. +# +#OPTIONS= + +# +# By default, the httpd process is started in the C locale; to  +# change the locale in which the server runs, the HTTPD_LANG +# variable can be set. +# +#HTTPD_LANG=C diff --git a/puppet/modules/apache/files/service/CentOS/httpd.worker b/puppet/modules/apache/files/service/CentOS/httpd.worker new file mode 100644 index 00000000..290923f5 --- /dev/null +++ b/puppet/modules/apache/files/service/CentOS/httpd.worker @@ -0,0 +1,22 @@ +# Configuration file for the httpd service. + +# +# The default processing model (MPM) is the process-based +# 'prefork' model.  A thread-based model, 'worker', is also +# available, but does not work with some modules (such as PHP). +# The service must be stopped before changing this variable. +# +HTTPD=/usr/sbin/httpd.worker + +# +# To pass additional options (for instance, -D definitions) to the +# httpd binary at startup, set OPTIONS here. +# +#OPTIONS= + +# +# By default, the httpd process is started in the C locale; to  +# change the locale in which the server runs, the HTTPD_LANG +# variable can be set. +# +#HTTPD_LANG=C diff --git a/puppet/modules/apache/files/vhosts.d/CentOS/0-default.conf b/puppet/modules/apache/files/vhosts.d/CentOS/0-default.conf new file mode 100644 index 00000000..a8a84813 --- /dev/null +++ b/puppet/modules/apache/files/vhosts.d/CentOS/0-default.conf @@ -0,0 +1,11 @@ +############################################################ +### This file is managed by PUPPET!                     #### +### Only modify in repo or you will loose the changes!  #### +############################################################ + +<VirtualHost *:80> +    Include include.d/defaults.inc +    DocumentRoot /var/www/html +</VirtualHost> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/vhosts.d/Debian/0-default.conf b/puppet/modules/apache/files/vhosts.d/Debian/0-default.conf new file mode 100644 index 00000000..2cbd90fe --- /dev/null +++ b/puppet/modules/apache/files/vhosts.d/Debian/0-default.conf @@ -0,0 +1,41 @@ +<VirtualHost *:80> +	ServerAdmin webmaster@localhost +	 +	DocumentRoot /var/www/ +	<Directory /> +		Options FollowSymLinks +		AllowOverride None +	</Directory> +	<Directory /var/www/> +		Options Indexes FollowSymLinks MultiViews +		AllowOverride None +		Order allow,deny +		allow from all +	</Directory> + +	ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ +	<Directory "/usr/lib/cgi-bin"> +		AllowOverride None +		Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch +		Order allow,deny +		Allow from all +	</Directory> + +	ErrorLog /var/log/apache2/error.log + +	# Possible values include: debug, info, notice, warn, error, crit, +	# alert, emerg. +	LogLevel warn + +	CustomLog /var/log/apache2/access.log combined + +    Alias /doc/ "/usr/share/doc/" +    <Directory "/usr/share/doc/"> +        Options Indexes MultiViews FollowSymLinks +        AllowOverride None +        Order deny,allow +        Deny from all +        Allow from 127.0.0.0/255.0.0.0 ::1/128 +    </Directory> + +</VirtualHost> diff --git a/puppet/modules/apache/files/vhosts.d/Gentoo/0-default.conf b/puppet/modules/apache/files/vhosts.d/Gentoo/0-default.conf new file mode 100644 index 00000000..03468459 --- /dev/null +++ b/puppet/modules/apache/files/vhosts.d/Gentoo/0-default.conf @@ -0,0 +1,51 @@ +# ########################################################### +# ### this file is managed by PUPPET                     #### +# ### only modify in svn or you will loose the changes ! #### +# ########################################################### +# Virtual Hosts +# +# If you want to maintain multiple domains/hostnames on your +# machine you can setup VirtualHost containers for them. Most configurations +# use only name-based virtual hosts so the server doesn't need to worry about +# IP addresses. This is indicated by the asterisks in the directives below. +# +# Please see the documentation at +# <URL:http://httpd.apache.org/docs/2.2/vhosts/> +# for further details before you try to setup virtual hosts. +# +# You may use the command line option '-S' to verify your virtual host +# configuration. + +<IfDefine DEFAULT_VHOST> +# see bug #178966 why this is in here + +# Listen: Allows you to bind Apache to specific IP addresses and/or +# ports, instead of the default. See also the <VirtualHost> +# directive. +# +# Change this to Listen on specific IP addresses as shown below to +# prevent Apache from glomming onto all bound IP addresses. +# +#Listen 12.34.56.78:80 +Listen 80 + +# Use name-based virtual hosting. +NameVirtualHost *:80 + +# When virtual hosts are enabled, the main host defined in the default +# httpd.conf configuration will go away. We redefine it here so that it is +# still available. +# +# If you disable this vhost by removing -D DEFAULT_VHOST from +# /etc/conf.d/apache2, the first defined virtual host elsewhere will be +# the default. +<VirtualHost *:80> +	Include /etc/apache2/vhosts.d/default_vhost.include + +	<IfModule mpm_peruser_module> +		ServerEnvironment apache apache +	</IfModule> +</VirtualHost> +</IfDefine> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/vhosts.d/Gentoo/default_vhost.include b/puppet/modules/apache/files/vhosts.d/Gentoo/default_vhost.include new file mode 100644 index 00000000..590c1848 --- /dev/null +++ b/puppet/modules/apache/files/vhosts.d/Gentoo/default_vhost.include @@ -0,0 +1,79 @@ +# ########################################################### +# # copyleft 2008 immerda.ch +# ########################################################### +# ### this file is managed by PUPPET                     #### +# ### only modify in svn or you will loose the changes ! #### +# ########################################################### +# ServerAdmin: Your address, where problems with the server should be +# e-mailed.  This address appears on some server-generated pages, such +# as error documents.  e.g. admin@your-domain.com +ServerAdmin root@localhost + +# DocumentRoot: The directory out of which you will serve your +# documents. By default, all requests are taken from this directory, but +# symbolic links and aliases may be used to point to other locations. +# +# If you change this to something that isn't under /var/www then suexec +# will no longer work. +DocumentRoot "/var/www/localhost/htdocs" + +# This should be changed to whatever you set DocumentRoot to. +<Directory "/var/www/localhost/htdocs"> +	# Possible values for the Options directive are "None", "All", +	# or any combination of: +	#   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews +	# +	# Note that "MultiViews" must be named *explicitly* --- "Options All" +	# doesn't give it to you. +	# +	# The Options directive is both complicated and important.  Please see +	# http://httpd.apache.org/docs/2.2/mod/core.html#options +	# for more information. +	Options Indexes FollowSymLinks + +	# AllowOverride controls what directives may be placed in .htaccess files. +	# It can be "All", "None", or any combination of the keywords: +	#   Options FileInfo AuthConfig Limit +	AllowOverride All + +	# Controls who can get stuff from this server. +	Order allow,deny +	Allow from all +</Directory> + +<IfModule alias_module> +	# Redirect: Allows you to tell clients about documents that used to +	# exist in your server's namespace, but do not anymore. The client +	# will make a new request for the document at its new location. +	# Example: +	#   Redirect permanent /foo http://www.example.com/bar + +	# Alias: Maps web paths into filesystem paths and is used to +	# access content that does not live under the DocumentRoot. +	# Example: +	#   Alias /webpath /full/filesystem/path +	# +	# If you include a trailing / on /webpath then the server will +	# require it to be present in the URL.  You will also likely +	# need to provide a <Directory> section to allow access to +	# the filesystem path. + +	# ScriptAlias: This controls which directories contain server scripts. +	# ScriptAliases are essentially the same as Aliases, except that +	# documents in the target directory are treated as applications and +	# run by the server when requested rather than as documents sent to the +	# client.  The same rules about trailing "/" apply to ScriptAlias +	# directives as to Alias. +	ScriptAlias /cgi-bin/ "/var/www/localhost/cgi-bin/" +</IfModule> + +# "/var/www/localhost/cgi-bin" should be changed to whatever your ScriptAliased +# CGI directory exists, if you have that configured. +<Directory "/var/www/localhost/cgi-bin"> +	AllowOverride None +	Options None +	Order allow,deny +	Allow from all +</Directory> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/files/vhosts.d/OpenBSD/0-default.conf b/puppet/modules/apache/files/vhosts.d/OpenBSD/0-default.conf new file mode 100644 index 00000000..9c4aa9d5 --- /dev/null +++ b/puppet/modules/apache/files/vhosts.d/OpenBSD/0-default.conf @@ -0,0 +1,8 @@ +<VirtualHost *:80> +    Include include.d/defaults.inc + +    DocumentRoot /var/www/htdocs/default/www/ +    ErrorLog /var/www/htdocs/default/logs/default_error_log +    CustomLog /var/www/htdocs/default/logs/default_access_log combined +</VirtualHost> + diff --git a/puppet/modules/apache/lib/facter/apache_version.rb b/puppet/modules/apache/lib/facter/apache_version.rb new file mode 100644 index 00000000..f0521832 --- /dev/null +++ b/puppet/modules/apache/lib/facter/apache_version.rb @@ -0,0 +1,28 @@ +# determine the version of apache installed +  +def parse_version(version_string) +  version = "" +  version_string.each_line do |line| +    if line.match(/^Server version/) +      version = line.scan(/Apache\/(.*) /)[0][0] +    end +  end +  return version +end +  +Facter.add('apache_version') do +  setcode do +    case Facter.value('osfamily') +    when /RedHat/ +      if File.exists?('/usr/sbin/httpd') +        version = parse_version(%x(/usr/sbin/httpd -v)) +      end +    when /Debian/ +      if File.exists?('/usr/sbin/apache2') +        version = parse_version(%x(/usr/sbin/apache2 -v)) +      end +    else +      version = 'undef' +    end +  end +end diff --git a/puppet/modules/apache/lib/puppet/parser/functions/guess_apache_version.rb b/puppet/modules/apache/lib/puppet/parser/functions/guess_apache_version.rb new file mode 100644 index 00000000..7537f6d9 --- /dev/null +++ b/puppet/modules/apache/lib/puppet/parser/functions/guess_apache_version.rb @@ -0,0 +1,39 @@ +# Try to guess the version of apache to be installed. +# Certain apache modules depend on each other, so we +# need to evaluate the apache version before it gets +# installed. This function decides which apache version +# is going to be installed based on the `operatingsystemrelease` +# fact. +module Puppet::Parser::Functions +  newfunction(:guess_apache_version, :type => :rvalue) do |args| +    release = lookupvar('operatingsystemrelease') +    unknown = 'unknown' + +    case lookupvar('operatingsystem') + +      when 'Debian' +        case release +          when /^7.*/ +            version = '2.2' +          when /^8.*/ +            version = '2.4' +          else +            version = unknown +        end + +      when 'Ubuntu' +        case release +          when /(12.04|12.10|13.04|13.10)/ +            version = '2.2' +          when /(14.04|14.10|15.04|15.10|16.04)/ +            version = '2.4' +          else +            version = unknown +        end + +      else +        version = unknown +    end +    version +  end +end diff --git a/puppet/modules/apache/lib/puppet/parser/functions/htpasswd_sha1.rb b/puppet/modules/apache/lib/puppet/parser/functions/htpasswd_sha1.rb new file mode 100644 index 00000000..937621d9 --- /dev/null +++ b/puppet/modules/apache/lib/puppet/parser/functions/htpasswd_sha1.rb @@ -0,0 +1,8 @@ +require 'digest/sha1'  +require 'base64' + +module Puppet::Parser::Functions +  newfunction(:htpasswd_sha1, :type => :rvalue) do |args| +    "{SHA}" + Base64.encode64(Digest::SHA1.digest(args[0])) +  end +end diff --git a/puppet/modules/apache/manifests/base.pp b/puppet/modules/apache/manifests/base.pp new file mode 100644 index 00000000..3f921599 --- /dev/null +++ b/puppet/modules/apache/manifests/base.pp @@ -0,0 +1,75 @@ +# setup base apache class +class apache::base { +  file{ +    'vhosts_dir': +      ensure  => directory, +      path    => '/etc/apache2/vhosts.d', +      purge   => true, +      recurse => true, +      force   => true, +      notify  => Service['apache'], +      owner   => root, +      group   => 0, +      mode    => '0644'; +    'config_dir': +      ensure  => directory, +      path    => '/etc/apache2/conf.d', +      owner   => root, +      group   => 0, +      mode    => '0644'; +    'include_dir': +      ensure  => directory, +      path    => '/etc/apache2/include.d', +      purge   => true, +      recurse => true, +      force   => true, +      notify  => Service['apache'], +      owner   => root, +      group   => 0, +      mode    => '0644'; +    'modules_dir': +      ensure  => directory, +      path    => '/etc/apache2/modules.d', +      purge   => true, +      recurse => true, +      force   => true, +      notify  => Service['apache'], +      owner   => root, +      group   => 0, +      mode    => '0644'; +    'htpasswd_dir': +      ensure  => directory, +      path    => '/var/www/htpasswds', +      purge   => true, +      recurse => true, +      force   => true, +      notify  => Service['apache'], +      owner   => root, +      group   => 'apache', +      mode    => '0640'; +    'web_dir': +      ensure  => directory, +      path    => '/var/www', +      owner   => root, +      group   => 0, +      mode    => '0644'; +    'default_apache_index': +      path    => '/var/www/localhost/htdocs/index.html', +      content => template('apache/default/default_index.erb'), +      owner   => root, +      group   => 0, +      mode    => '0644'; +  } -> anchor{'apache::basic_dirs::ready': } + +  apache::config::include{ 'defaults.inc': } +  apache::config::global{ 'git.conf': } +  if !$apache::no_default_site { +    apache::vhost::file { '0-default': } +  } + +  service{'apache': +    ensure => running, +    name   => 'apache2', +    enable => true, +  } +} diff --git a/puppet/modules/apache/manifests/base/itk.pp b/puppet/modules/apache/manifests/base/itk.pp new file mode 100644 index 00000000..7772bfdf --- /dev/null +++ b/puppet/modules/apache/manifests/base/itk.pp @@ -0,0 +1,6 @@ +class apache::base::itk inherits apache::base { +    File['htpasswd_dir']{ +        group => 0, +        mode => 0644, +    } +} diff --git a/puppet/modules/apache/manifests/centos.pp b/puppet/modules/apache/manifests/centos.pp new file mode 100644 index 00000000..f4697155 --- /dev/null +++ b/puppet/modules/apache/manifests/centos.pp @@ -0,0 +1,86 @@ +### centos +class apache::centos inherits apache::package { +  $config_dir = '/etc/httpd' + +  Package[apache]{ +    name => 'httpd', +  } +  Service[apache]{ +    name    => 'httpd', +    restart => '/etc/init.d/httpd graceful', +  } +  File[vhosts_dir]{ +    path => "${config_dir}/vhosts.d", +  } +  File[config_dir]{ +    path => "${config_dir}/conf.d", +  } +  File[include_dir]{ +    path => "${config_dir}/include.d", +  } +  File[modules_dir]{ +    path => "${config_dir}/modules.d", +  } +  File[web_dir]{ +    path => '/var/www/vhosts', +  } +  File[default_apache_index]{ +    path => '/var/www/html/index.html', +  } + +  if str2bool($::selinux) { +    Selinux::Fcontext{ +      before => File[web_dir], +    } +    $seltype_rw = $::operatingsystemmajrelease ? { +      5       => 'httpd_sys_script_rw_t', +      default => 'httpd_sys_rw_content_t' +    } +    selinux::fcontext{ +      [ '/var/www/vhosts/[^/]*/www(/.*)?', +        '/var/www/vhosts/[^/]*/non_public(/.*)?', +        '/var/www/vhosts/[^/]*/data(/.*)?', +        '/var/www/vhosts/[^/]*/upload(/.*)?' ]: +        require => Package['apache'], +        setype  => $seltype_rw; +      '/var/www/vhosts/[^/]*/logs(/.*)?': +        require => Package['apache'], +        setype  => 'httpd_log_t'; +    } +  } +  file{'apache_service_config': +    path    => '/etc/sysconfig/httpd', +    source  => [  "puppet:///modules/site_apache/service/CentOS/${::fqdn}/httpd", +                  'puppet:///modules/site_apache/service/CentOS/httpd', +                  'puppet:///modules/apache/service/CentOS/httpd' ], +    require => Package['apache'], +    notify  => Service['apache'], +    owner   => root, +    group   => 0, +    mode    => '0644'; +  } + +  # this is for later fixes +  exec{ +    'adjust_pidfile': +      command => 'sed -i  "s/^#PidFile \(.*\)/PidFile \1/g" /etc/httpd/conf/httpd.conf', +      unless  => 'grep -qE \'^PidFile \' /etc/httpd/conf/httpd.conf', +      require => Package['apache'], +      notify  => Service['apache']; +    'adjust_listen': +      command => 'sed -i  "s/^#Listen 80/Listen 80/g" /etc/httpd/conf/httpd.conf', +      unless  => 'grep -qE \'^Listen 80\' /etc/httpd/conf/httpd.conf', +      require => Package['apache'], +      notify  => Service['apache']; +  } + +  apache::config::global{'00-listen.conf': +    ensure => absent, +  } + +  include apache::logrotate::centos + +  apache::config::global{ 'welcome.conf': } +  apache::config::global{ 'vhosts.conf': } +} + diff --git a/puppet/modules/apache/manifests/centos/itk.pp b/puppet/modules/apache/manifests/centos/itk.pp new file mode 100644 index 00000000..20f4270d --- /dev/null +++ b/puppet/modules/apache/manifests/centos/itk.pp @@ -0,0 +1,10 @@ +# http://hostby.net/home/2008/07/12/centos-5-and-mpm-itk/ +class apache::centos::itk inherits apache::centos { +    include ::apache::base::itk +    Package['apache']{ +        name => 'httpd-itk', +    } +    File['apache_service_config']{ +      source => "puppet:///modules/apache/service/${::operatingsystem}/httpd.itk" +    } +} diff --git a/puppet/modules/apache/manifests/centos/itk_plus.pp b/puppet/modules/apache/manifests/centos/itk_plus.pp new file mode 100644 index 00000000..0df92c84 --- /dev/null +++ b/puppet/modules/apache/manifests/centos/itk_plus.pp @@ -0,0 +1,20 @@ +# http://hostby.net/home/2008/07/12/centos-5-and-mpm-itk/ +class apache::centos::itk_plus inherits apache::centos::itk { +  Exec['adjust_pidfile']{ +    command => "sed -i  's/^PidFile \\(.*\\)/#PidFile \\1/g' /etc/httpd/conf/httpd.conf", +    unless => "grep -qE '^#PidFile ' /etc/httpd/conf/httpd.conf", +  } +  Exec['adjust_listen']{ +    command => "sed -i  's/^Listen 80/#Listen 80/g' /etc/httpd/conf/httpd.conf", +    unless => "grep -qE '^#Listen 80' /etc/httpd/conf/httpd.conf", +  } + +  Apache::Config::Global['00-listen.conf']{ +    ensure => 'present', +    content => template("apache/itk_plus/${::operatingsystem}/00-listen.conf.erb"), +  } + +  File['apache_service_config']{ +    source => "puppet:///modules/apache/service/CentOS/httpd.itk_plus" +  } +} diff --git a/puppet/modules/apache/manifests/centos/module.pp b/puppet/modules/apache/manifests/centos/module.pp new file mode 100644 index 00000000..3220d1f8 --- /dev/null +++ b/puppet/modules/apache/manifests/centos/module.pp @@ -0,0 +1,30 @@ +define apache::centos::module( +    $ensure = present, +    $source = '', +    $destination = '' +){ +    $modules_dir = "${apache::centos::config_dir}/modules.d" +    $real_destination = $destination ? { +        '' => "${modules_dir}/${name}.so", +        default => $destination, +    } +    $real_source = $source ? { +        ''  => [ +            "puppet:///modules/site_apache/modules.d/${::fqdn}/${name}.so", +            "puppet:///modules/site_apache/modules.d/${apache::cluster_node}/${name}.so", +            "puppet:///modules/site_apache/modules.d/${name}.so", +            "puppet:///modules/apache/modules.d/${::operatingsystem}/${name}.so", +            "puppet:///modules/apache/modules.d/${name}.so" +        ], +        default => "puppet:///$source", +    } +    file{"modules_${name}.conf": +        ensure => $ensure, +        path => $real_destination, +        source => $real_source, +        require => [ File[modules_dir], Package[apache] ], +        notify => Service[apache], +        owner => root, group => 0, mode => 0755; +    } +} + diff --git a/puppet/modules/apache/manifests/centos/worker.pp b/puppet/modules/apache/manifests/centos/worker.pp new file mode 100644 index 00000000..f374bb70 --- /dev/null +++ b/puppet/modules/apache/manifests/centos/worker.pp @@ -0,0 +1,5 @@ +class apache::centos::worker inherits apache::centos { +    File['apache_service_config']{ +      source => "puppet:///modules/apache/service/${::operatingsystem}/httpd.worker" +    } +} diff --git a/puppet/modules/apache/manifests/config/file.pp b/puppet/modules/apache/manifests/config/file.pp new file mode 100644 index 00000000..7b058691 --- /dev/null +++ b/puppet/modules/apache/manifests/config/file.pp @@ -0,0 +1,106 @@ +# deploy apache configuration file +# by default we assume it's a global configuration file +define apache::config::file( +  $ensure     = present, +  $target     = false, +  $type       = 'global', +  $source     = 'absent', +  $content    = 'absent', +  $destination = 'absent' +){ +  case $type { +    'include': { $confdir = 'include.d' } +    'global': { $confdir = 'conf.d' } +    default: { fail("Wrong config file type specified for ${name}") } +  } +  $real_destination = $destination ? { +    'absent'  => $::operatingsystem ? { +      centos    => "${apache::centos::config_dir}/${confdir}/${name}", +      gentoo    => "${apache::gentoo::config_dir}/${name}", +      debian    => "${apache::debian::config_dir}/${confdir}/${name}", +      ubuntu    => "${apache::ubuntu::config_dir}/${confdir}/${name}", +      openbsd   => "${apache::openbsd::config_dir}/${confdir}/${name}", +      default   => "/etc/apache2/${confdir}/${name}", +    }, +    default => $destination +  } +  file{"apache_${name}": +    ensure  => $ensure, +    path    => $real_destination, +    notify  => Service[apache], +    owner   => root, +    group   => 0, +    mode    => '0644'; +  } + +  case $ensure { +    'absent', 'purged': { +      # We want to avoid all stuff related to source and content +    } +    'link': { +      if $target { +        File["apache_${name}"] { +          target => $target, +        } +      } +    } +    default: { +      case $content { +        'absent': { +          $real_source = $source ? { +            'absent' => [ +              "puppet:///modules/site_apache/${confdir}/${::fqdn}/${name}", +              "puppet:///modules/site_apache/${confdir}/${apache::cluster_node}/${name}", +              "puppet:///modules/site_apache/${confdir}/${::operatingsystem}.${::operatingsystemmajrelease}/${name}", +              "puppet:///modules/site_apache/${confdir}/${::operatingsystem}/${name}", +              "puppet:///modules/site_apache/${confdir}/${name}", +              "puppet:///modules/apache/${confdir}/${::operatingsystem}.${::operatingsystemmajrelease}/${name}", +              "puppet:///modules/apache/${confdir}/${::operatingsystem}/${name}", +              "puppet:///modules/apache/${confdir}/${name}" +            ], +            default => $source +          } +          File["apache_${name}"]{ +            source => $real_source, +          } +        } +        default: { +          case $content { +            'absent': { +              $real_source = $source ? { +                'absent' => [ +                    "puppet:///modules/site-apache/${confdir}/${::fqdn}/${name}", +                    "puppet:///modules/site-apache/${confdir}/${apache::cluster_node}/${name}", +                    "puppet:///modules/site-apache/${confdir}/${::operatingsystem}.${::operatingsystemmajrelease}/${name}", +                    "puppet:///modules/site-apache/${confdir}/${::operatingsystem}/${name}", +                    "puppet:///modules/site-apache/${confdir}/${name}", +                    "puppet:///modules/apache/${confdir}/${::operatingsystem}.${::operatingsystemmajrelease}/${name}", +                    "puppet:///modules/apache/${confdir}/${::operatingsystem}/${name}", +                    "puppet:///modules/apache/${confdir}/${name}" +                ], +                default => $source, +              } +              File["apache_${name}"]{ +                source => $real_source, +              } +            } +            default: { +              File["apache_${name}"]{ +                content => $content, +              } +            } +          } +        } +      } +    } +  } + +  case $::operatingsystem { +    openbsd: { info("no package dependency on ${::operatingsystem} for ${name}") } +    default: { +      File["apache_${name}"]{ +        require => Package[apache], +      } +    } +  } +} diff --git a/puppet/modules/apache/manifests/config/global.pp b/puppet/modules/apache/manifests/config/global.pp new file mode 100644 index 00000000..8b0389be --- /dev/null +++ b/puppet/modules/apache/manifests/config/global.pp @@ -0,0 +1,18 @@ +# deploy apache configuration file (global) +# wrapper for apache::config::file +define apache::config::global( +    $ensure = present, +    $target = false, +    $source = 'absent', +    $content = 'absent', +    $destination = 'absent' +){ +    apache::config::file { "${name}": +        ensure => $ensure, +        target => $target, +        type => 'global', +        source => $source, +        content => $content, +        destination => $destination, +    } +} diff --git a/puppet/modules/apache/manifests/config/include.pp b/puppet/modules/apache/manifests/config/include.pp new file mode 100644 index 00000000..4d676f05 --- /dev/null +++ b/puppet/modules/apache/manifests/config/include.pp @@ -0,0 +1,17 @@ +# deploy apache configuration file (includes for vhosts) +define apache::config::include( +    $ensure = present, +    $target = false, +    $source = 'absent', +    $content = 'absent', +    $destination = 'absent' +){ +    apache::config::file { "${name}": +        ensure => $ensure, +        target => $target, +        type => 'include', +        source => $source, +        content => $content, +        destination => $destination, +    } +} diff --git a/puppet/modules/apache/manifests/debian.pp b/puppet/modules/apache/manifests/debian.pp new file mode 100644 index 00000000..6ae4cee8 --- /dev/null +++ b/puppet/modules/apache/manifests/debian.pp @@ -0,0 +1,44 @@ +### debian +class apache::debian inherits apache::package { +  $config_dir = '/etc/apache2' + +  Package[apache] { +    name => 'apache2', +  } +  File[vhosts_dir] { +    path => "${config_dir}/sites-enabled", +  } +  File[modules_dir] { +    path => "${config_dir}/mods-enabled", +  } +  File[htpasswd_dir] { +    path   => '/var/www/htpasswds', +    group  => 'www-data', +  } +  File[default_apache_index] { +    path => '/var/www/index.html', +  } +  file { 'apache_main_config': +    path    => "${config_dir}/apache2.conf", +    source  => [ "puppet:///modules/site_apache/config/Debian.${::lsbdistcodename}/${::fqdn}/apache2.conf", +                "puppet:///modules/site_apache/config/Debian/${::fqdn}/apache2.conf", +                "puppet:///modules/site_apache/config/Debian.${::lsbdistcodename}/apache2.conf", +                'puppet:///modules/site_apache/config/Debian/apache2.conf', +                "puppet:///modules/apache/config/Debian.${::lsbdistcodename}/${::fqdn}/apache2.conf", +                "puppet:///modules/apache/config/Debian/${::fqdn}/apache2.conf", +                "puppet:///modules/apache/config/Debian.${::lsbdistcodename}/apache2.conf", +                'puppet:///modules/apache/config/Debian/apache2.conf' ], +    require => Package['apache'], +    notify  => Service['apache'], +    owner   => root, +    group   => 0, +    mode    => '0644'; +  } +  apache::config::global{ 'charset': } +  apache::config::global{ 'security': } +  file { 'default_debian_apache_vhost': +    ensure  => absent, +    path    => '/etc/apache2/sites-enabled/000-default', +  } +} + diff --git a/puppet/modules/apache/manifests/debian/itk.pp b/puppet/modules/apache/manifests/debian/itk.pp new file mode 100644 index 00000000..718a81b3 --- /dev/null +++ b/puppet/modules/apache/manifests/debian/itk.pp @@ -0,0 +1,9 @@ +class apache::debian::itk inherits apache::debian { +  File['htpasswd_dir']{ +    group => 0, +    mode => 0644, +  } +  Package['apache']{ +    name => 'apache2-mpm-itk', +  } +} diff --git a/puppet/modules/apache/manifests/debian/module.pp b/puppet/modules/apache/manifests/debian/module.pp new file mode 100644 index 00000000..ed255155 --- /dev/null +++ b/puppet/modules/apache/manifests/debian/module.pp @@ -0,0 +1,48 @@ +# install/remove apache module on debian/ubuntu systems +define apache::debian::module( +  $ensure = present, +  $package_name = 'absent', +  $conf_source = '', +  $conf_content = '', +){ +  $modules_dir = "${apache::debian::config_dir}/mods" + +  if ($package_name != 'absent') { +    package { $package_name: +      ensure  => $ensure, +      notify  => Service['apache'], +      require => [ File['modules_dir'], Package['apache'] ], +    } +    $required_packages = [ 'apache', $package_name ] +  } +  else { +    $required_packages = [ 'apache' ] +  } + +  file { +    "${modules_dir}-enabled/${name}.load": +      ensure  => "../mods-available/${name}.load", +      notify  => Service['apache'], +      require => [ File['modules_dir'], Package[$required_packages] ]; +    "${modules_dir}-enabled/${name}.conf": +      ensure  => "../mods-available/${name}.conf", +      notify  => Service['apache'], +      require => [ File['modules_dir'], Package[$required_packages] ]; +    "${modules_dir}-available/${name}.conf": +      ensure  => file, +      notify  => Service['apache'], +      require => [ File['modules_dir'], Package[$required_packages] ]; +  } + +  if $conf_content != '' { +    File["${modules_dir}-available/${name}.conf"] { +      content => $conf_content, +    } +  } +  elsif $conf_source != '' { +    File["${modules_dir}-available/${name}.conf"] { +      source => $conf_source, +    } +  } + +} diff --git a/puppet/modules/apache/manifests/defaultdavdbdir.pp b/puppet/modules/apache/manifests/defaultdavdbdir.pp new file mode 100644 index 00000000..c0e2a81a --- /dev/null +++ b/puppet/modules/apache/manifests/defaultdavdbdir.pp @@ -0,0 +1,17 @@ +class apache::defaultdavdbdir { +    file { +        '/var/www/dav_db_dir' : +            ensure => directory, +            require => Package['apache'], +            owner => root, +            group => 0, +            mode => 0755 ; +    } +    if $::selinux != 'false' { +        selinux::fcontext { +            ['/var/www/dav_db_dir/.+(/.*)?'] : +                setype => 'httpd_var_lib_t', +                before => File['/var/www/dav_db_dir'] ; +        } +    } +} diff --git a/puppet/modules/apache/manifests/defaultphpdirs.pp b/puppet/modules/apache/manifests/defaultphpdirs.pp new file mode 100644 index 00000000..595744bb --- /dev/null +++ b/puppet/modules/apache/manifests/defaultphpdirs.pp @@ -0,0 +1,31 @@ +# setup some directories for php +class apache::defaultphpdirs { +    file{ +      '/var/www/upload_tmp_dir': +        ensure  => directory, +        require => Package['apache'], +        owner   => root, +        group   => 0, +        mode    => '0755'; +      '/var/www/session.save_path': +        ensure  => directory, +        require => Package['apache'], +        owner   => root, +        group   => 0, +        mode    => '0755'; +    } + +    if str2bool($::selinux) { +      $seltype_rw = $::operatingsystemmajrelease ? { +        5       => 'httpd_sys_script_rw_t', +        default => 'httpd_sys_rw_content_t' +      } +      selinux::fcontext{ +        [ '/var/www/upload_tmp_dir/.+(/.*)?', +          '/var/www/session.save_path/.+(/.*)?' ]: +          require => Package['apache'], +          setype  => $seltype_rw, +          before  => File['/var/www/upload_tmp_dir','/var/www/session.save_path']; +      } +    } +} diff --git a/puppet/modules/apache/manifests/file.pp b/puppet/modules/apache/manifests/file.pp new file mode 100644 index 00000000..b0a60ecb --- /dev/null +++ b/puppet/modules/apache/manifests/file.pp @@ -0,0 +1,15 @@ +define apache::file( +    $owner = root, +    $group = 0, +    $mode = 0640 +) { +    file{$name: +# as long as there are significant memory problems using +# recurse we avoid it +#        recurse => true, +        backup => false, +        checksum => undef, +        owner => $owner, group => $group, mode => $mode; +    } +} + diff --git a/puppet/modules/apache/manifests/file/readonly.pp b/puppet/modules/apache/manifests/file/readonly.pp new file mode 100644 index 00000000..6308d889 --- /dev/null +++ b/puppet/modules/apache/manifests/file/readonly.pp @@ -0,0 +1,12 @@ +define apache::file::readonly( +    $owner = root, +    $group = 0, +    $mode = 0640 +) { +    apache::file{$name: +        owner => $owner, +        group => $group, +        mode => $mode, +    } +} + diff --git a/puppet/modules/apache/manifests/file/rw.pp b/puppet/modules/apache/manifests/file/rw.pp new file mode 100644 index 00000000..0f258bf3 --- /dev/null +++ b/puppet/modules/apache/manifests/file/rw.pp @@ -0,0 +1,13 @@ +# a file that is writable by apache +define apache::file::rw( +  $owner  = root, +  $group  = 0, +  $mode   = '0660', +) { +  apache::file{$name: +    owner => $owner, +    group => $group, +    mode  => $mode, +  } +} + diff --git a/puppet/modules/apache/manifests/gentoo.pp b/puppet/modules/apache/manifests/gentoo.pp new file mode 100644 index 00000000..3a13977f --- /dev/null +++ b/puppet/modules/apache/manifests/gentoo.pp @@ -0,0 +1,39 @@ +### gentoo +class apache::gentoo inherits apache::package { +  $config_dir = '/etc/apache2' + +  # needs module gentoo +  gentoo::etcconfd { +    'apache2': +      require => Package['apache'], +      notify  => Service['apache'], +  } +  Package['apache']{ +    category => 'www-servers', +  } +  File[vhosts_dir]{ +    path => "${config_dir}/vhosts.d", +  } +  File[modules_dir]{ +    path => "${config_dir}/modules.d", +  } + +  apache::gentoo::module{ +    '00_default_settings':; +    '00_error_documents':; +  } +  apache::config::file { 'default_vhost.include': +      source      => 'apache/vhosts.d/default_vhost.include', +      destination => "${config_dir}/vhosts.d/default_vhost.include", +  } + +  # set the default for the ServerName +  file{"${config_dir}/modules.d/00_default_settings_ServerName.conf": +      content => "ServerName ${::fqdn}\n", +      require => Package[apache], +      owner   => root, +      group   => 0, +      mode    => '0644'; +  } +} + diff --git a/puppet/modules/apache/manifests/gentoo/module.pp b/puppet/modules/apache/manifests/gentoo/module.pp new file mode 100644 index 00000000..1e9d03a6 --- /dev/null +++ b/puppet/modules/apache/manifests/gentoo/module.pp @@ -0,0 +1,30 @@ +define apache::gentoo::module( +    $ensure = present, +    $source = '', +    $destination = '' +){ +    $modules_dir = "${apache::gentoo::config_dir}/modules.d" +    $real_destination = $destination ? { +        '' => "${modules_dir}/${name}.conf", +        default => $destination, +    } +    $real_source = $source ? { +        ''  => [ +            "puppet:///modules/site_apache/modules.d/${::fqdn}/${name}.conf", +            "puppet:///modules/site_apache/modules.d/${apache::cluster_node}/${name}.conf", +            "puppet:///modules/site_apache/modules.d/${name}.conf", +            "puppet:///modules/apache/modules.d/${::operatingsystem}/${name}.conf", +            "puppet:///modules/apache/modules.d/${name}.conf" +        ], +        default => "puppet:///$source", +    } +    file{"modules_${name}.conf": +        ensure => $ensure, +        path => $real_destination, +        source => $real_source, +        require => [ File[modules_dir], Package[apache] ], +        notify => Service[apache], +        owner => root, group => 0, mode => 0644; +    } +} + diff --git a/puppet/modules/apache/manifests/htpasswd_user.pp b/puppet/modules/apache/manifests/htpasswd_user.pp new file mode 100644 index 00000000..82fbce45 --- /dev/null +++ b/puppet/modules/apache/manifests/htpasswd_user.pp @@ -0,0 +1,34 @@ +# ToDo: This should be rewritten as native type +define apache::htpasswd_user( +    $password, +    $password_iscrypted = false, +    $ensure   = 'present', +    $site     = 'absent', +    $username = 'absent', +    $path     = 'absent' +){ +    case $username { +        'absent': { $real_username = $name } +        default: { $real_username = $username } +    } +    case $site { +        'absent': { $real_site = $name } +        default: { $real_site = $site } +    } +    if $password_iscrypted { +        $real_password = $password +    } else { +        $real_password = htpasswd_sha1($password) +    } + +    case $path { +        'absent': { $real_path = "/var/www/htpasswds/${real_site}" } +        default:  { $real_path = $path } +    } + +    file_line{"htpasswd_for_${real_site}": +        ensure => $ensure, +        path   => $real_path, +        line   => "${username}:${real_password}", +    } +} diff --git a/puppet/modules/apache/manifests/include/joomla.pp b/puppet/modules/apache/manifests/include/joomla.pp new file mode 100644 index 00000000..5adae30a --- /dev/null +++ b/puppet/modules/apache/manifests/include/joomla.pp @@ -0,0 +1,3 @@ +class apache::include::joomla { +    apache::config::include{'joomla.inc': } +} diff --git a/puppet/modules/apache/manifests/include/mod_fcgid.pp b/puppet/modules/apache/manifests/include/mod_fcgid.pp new file mode 100644 index 00000000..b3c1cdc2 --- /dev/null +++ b/puppet/modules/apache/manifests/include/mod_fcgid.pp @@ -0,0 +1,7 @@ +class apache::include::mod_fcgid { +  apache::config::global{'mod_fcgid.conf': +    content => "<IfModule mod_fcgid.c> +  FcgidFixPathinfo 1 +</IfModule>\n" +  } +} diff --git a/puppet/modules/apache/manifests/include/silverstripe.pp b/puppet/modules/apache/manifests/include/silverstripe.pp new file mode 100644 index 00000000..fd2484b7 --- /dev/null +++ b/puppet/modules/apache/manifests/include/silverstripe.pp @@ -0,0 +1,3 @@ +class apache::include::silverstripe { +    apache::config::include{'silverstripe.inc': } +} diff --git a/puppet/modules/apache/manifests/includes.pp b/puppet/modules/apache/manifests/includes.pp new file mode 100644 index 00000000..02502f82 --- /dev/null +++ b/puppet/modules/apache/manifests/includes.pp @@ -0,0 +1,5 @@ +# manifests/includes.pp + +class apache::includes { +    apache::config::global{'do_includes.conf':} +} diff --git a/puppet/modules/apache/manifests/init.pp b/puppet/modules/apache/manifests/init.pp new file mode 100644 index 00000000..ad1478a1 --- /dev/null +++ b/puppet/modules/apache/manifests/init.pp @@ -0,0 +1,44 @@ +# +# apache module +# +# Copyright 2008, admin(at)immerda.ch +# Copyright 2008, Puzzle ITC GmbH +# Marcel Haerry haerry+puppet(at)puzzle.ch +# Simon Josi josi+puppet(at)puzzle.ch +# +# This program is free software; you can redistribute +# it and/or modify it under the terms of the GNU +# General Public License version 3 as published by +# the Free Software Foundation. +# + +# manage a simple apache +class apache( +  $cluster_node                       = '', +  $manage_shorewall                   = false, +  $manage_munin                       = false, +  $no_default_site                    = false, +  $ssl                                = false, +  $default_ssl_certificate_file       = absent, +  $default_ssl_certificate_key_file   = absent, +  $default_ssl_certificate_chain_file = absent, +  $ssl_cipher_suite                   = 'HIGH:MEDIUM:!aNULL:!MD5' +) { +  case $::operatingsystem { +    centos: { include apache::centos } +    gentoo: { include apache::gentoo } +    debian,ubuntu: { include apache::debian } +    openbsd: { include apache::openbsd } +    default: { include apache::base } +  } +  if $apache::manage_munin { +    include apache::status +  } +  if $apache::manage_shorewall { +    include shorewall::rules::http +  } +  if $ssl { +    include apache::ssl +  } +} + diff --git a/puppet/modules/apache/manifests/itk.pp b/puppet/modules/apache/manifests/itk.pp new file mode 100644 index 00000000..5292343d --- /dev/null +++ b/puppet/modules/apache/manifests/itk.pp @@ -0,0 +1,11 @@ +# manifests/itk.pp +# +# see: http://mpm-itk.sesse.net/ + +class apache::itk inherits apache { +    case $::operatingsystem { +        centos: { include ::apache::centos::itk } +        debian: { include ::apache::debian::itk } +        default: { include ::apache::base::itk } +    } +} diff --git a/puppet/modules/apache/manifests/itk/lock.pp b/puppet/modules/apache/manifests/itk/lock.pp new file mode 100644 index 00000000..4ad95faf --- /dev/null +++ b/puppet/modules/apache/manifests/itk/lock.pp @@ -0,0 +1,4 @@ +class apache::itk::lock { +  # This file resource is used to ensure that only one itk mode is used per host +  file{'/var/www/.itk_mode_lock': ensure => absent } +} diff --git a/puppet/modules/apache/manifests/itk_plus.pp b/puppet/modules/apache/manifests/itk_plus.pp new file mode 100644 index 00000000..7d9f721a --- /dev/null +++ b/puppet/modules/apache/manifests/itk_plus.pp @@ -0,0 +1,10 @@ +# manifests/itk.pp +# +# see: http://mpm-itk.sesse.net/ + +class apache::itk_plus inherits apache::itk { +    case $::operatingsystem { +        centos: { include ::apache::centos::itk_plus } +        default: { fail("itk plus mode is currently only implemented for CentOS") } +    } +} diff --git a/puppet/modules/apache/manifests/itk_plus/lock.pp b/puppet/modules/apache/manifests/itk_plus/lock.pp new file mode 100644 index 00000000..d540939d --- /dev/null +++ b/puppet/modules/apache/manifests/itk_plus/lock.pp @@ -0,0 +1,4 @@ +class apache::itk_plus::lock { +  # This file resource is used to ensure that only one itk mode is used per host +  file{'/var/www/.itk_mode_lock': ensure => absent } +} diff --git a/puppet/modules/apache/manifests/logrotate/centos.pp b/puppet/modules/apache/manifests/logrotate/centos.pp new file mode 100644 index 00000000..4381205d --- /dev/null +++ b/puppet/modules/apache/manifests/logrotate/centos.pp @@ -0,0 +1,10 @@ +# add vhost folders to logrotation +class apache::logrotate::centos { +    augeas{'logrotate_httpd': +      changes => [ 'rm /files/etc/logrotate.d/httpd/rule/file', +        'ins file before /files/etc/logrotate.d/httpd/rule/*[1]', +        'set /files/etc/logrotate.d/httpd/rule/file[1] /var/log/httpd/*log' ], +      onlyif  => 'get /files/etc/logrotate.d/httpd/rule/file[1] != "/var/log/httpd/*log"', +      require => Package['apache'], +    } +} diff --git a/puppet/modules/apache/manifests/logrotate/centos/vhosts.pp b/puppet/modules/apache/manifests/logrotate/centos/vhosts.pp new file mode 100644 index 00000000..b1159a11 --- /dev/null +++ b/puppet/modules/apache/manifests/logrotate/centos/vhosts.pp @@ -0,0 +1,11 @@ +# add vhost folders to logrotation +class apache::logrotate::centos::vhosts inherits apache::logrotate::centos { +    Augeas['logrotate_httpd']{ +      changes => [ 'rm /files/etc/logrotate.d/httpd/rule/file', +        'ins file before /files/etc/logrotate.d/httpd/rule/*[1]', +        'ins file before /files/etc/logrotate.d/httpd/rule/*[1]', +        'set /files/etc/logrotate.d/httpd/rule/file[1] /var/log/httpd/*log', +        'set /files/etc/logrotate.d/httpd/rule/file[2] /var/www/vhosts/*/logs/*log' ], +      onlyif => 'get /files/etc/logrotate.d/httpd/rule/file[2] != "/var/www/vhosts/*/logs/*log"', +    } +} diff --git a/puppet/modules/apache/manifests/mod_dav_svn.pp b/puppet/modules/apache/manifests/mod_dav_svn.pp new file mode 100644 index 00000000..bdcc4abd --- /dev/null +++ b/puppet/modules/apache/manifests/mod_dav_svn.pp @@ -0,0 +1,7 @@ +class apache::mod_dav_svn { +    package{'mod_dav_svn': +        ensure => installed, +        require => Package['apache'], +        notify => Service['apache'], +    } +} diff --git a/puppet/modules/apache/manifests/mod_macro.pp b/puppet/modules/apache/manifests/mod_macro.pp new file mode 100644 index 00000000..eed59e52 --- /dev/null +++ b/puppet/modules/apache/manifests/mod_macro.pp @@ -0,0 +1,7 @@ +class apache::mod_macro { +    package{'mod_macro': +        ensure => installed, +        require => Package['apache'], +        notify => Service['apache'], +    } +} diff --git a/puppet/modules/apache/manifests/module.pp b/puppet/modules/apache/manifests/module.pp new file mode 100644 index 00000000..cbcf2d04 --- /dev/null +++ b/puppet/modules/apache/manifests/module.pp @@ -0,0 +1,35 @@ +define apache::module ( +  $ensure = present, $source = '', +  $destination = '', $module = '', $package_name = 'absent', +  $conf_content = '', $conf_source = '', +) { + +  $real_module = $module ? { +    '' => $name, +    default => $module, +  } + +  case $operatingsystem { +    'centos': { +      apache::centos::module { "$real_module": +        ensure => $ensure, source => $source, +        destination => $destination +      } +    } +    'gentoo': { +      apache::gentoo::module { "$real_module": +        ensure => $ensure, source => $source, +        destination => $destination +      } +    } +    'debian','ubuntu': { +      apache::debian::module { "$real_module": +        ensure => $ensure, package_name => $package_name, +        conf_content => $conf_content, conf_source => $conf_source +      } +    } +    default: { +      err('Your operating system does not have a module deployment mechanism defined') +    } +  } +} diff --git a/puppet/modules/apache/manifests/module/alias.pp b/puppet/modules/apache/manifests/module/alias.pp new file mode 100644 index 00000000..33d26efe --- /dev/null +++ b/puppet/modules/apache/manifests/module/alias.pp @@ -0,0 +1,14 @@ +# install mod_alias +class apache::module::alias ( $ensure = present ) +{ + +  apache::module { 'alias': ensure => $ensure } + +  # from 2.4, /etc/apache2/mods-enabled/alias.conf contains the "Require" +  # directive which needs "authz_core" mod enabled + +  if ( guess_apache_version() == '2.4') { +    class { 'authz_core': ensure => $ensure } +  } + +} diff --git a/puppet/modules/apache/manifests/module/auth_basic.pp b/puppet/modules/apache/manifests/module/auth_basic.pp new file mode 100644 index 00000000..4335a09c --- /dev/null +++ b/puppet/modules/apache/manifests/module/auth_basic.pp @@ -0,0 +1,6 @@ +# enable/disable auth_basic module +class apache::module::auth_basic ( $ensure = present ) +{ + +  apache::module { 'auth_basic': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/authn_core.pp b/puppet/modules/apache/manifests/module/authn_core.pp new file mode 100644 index 00000000..46baace0 --- /dev/null +++ b/puppet/modules/apache/manifests/module/authn_core.pp @@ -0,0 +1,6 @@ +# enable/disable authn_core module +class apache::module::authn_core ( $ensure = present ) +{ + +  apache::module { 'authn_core': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/authn_file.pp b/puppet/modules/apache/manifests/module/authn_file.pp new file mode 100644 index 00000000..7c346d9b --- /dev/null +++ b/puppet/modules/apache/manifests/module/authn_file.pp @@ -0,0 +1,6 @@ +# enable/disable authn_file module +class apache::module::authn_file ( $ensure = present ) +{ + +  apache::module { 'authn_file': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/authz_core.pp b/puppet/modules/apache/manifests/module/authz_core.pp new file mode 100644 index 00000000..03b0617c --- /dev/null +++ b/puppet/modules/apache/manifests/module/authz_core.pp @@ -0,0 +1,7 @@ +# install mod_authz_core (needed i.e. by the alias mod config) +class apache::module::authz_core ( $ensure = present ) +{ + +  apache::module { 'authz_core': ensure => $ensure } + +} diff --git a/puppet/modules/apache/manifests/module/authz_host.pp b/puppet/modules/apache/manifests/module/authz_host.pp new file mode 100644 index 00000000..46c3a812 --- /dev/null +++ b/puppet/modules/apache/manifests/module/authz_host.pp @@ -0,0 +1,6 @@ +# enable/disable authz_host module +class apache::module::authz_host ( $ensure = present ) +{ + +  apache::module { 'authz_host': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/authz_user.pp b/puppet/modules/apache/manifests/module/authz_user.pp new file mode 100644 index 00000000..84775727 --- /dev/null +++ b/puppet/modules/apache/manifests/module/authz_user.pp @@ -0,0 +1,6 @@ +# enable/disable authz_user module +class apache::module::authz_user ( $ensure = present ) +{ + +  apache::module { 'authz_user': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/cgi.pp b/puppet/modules/apache/manifests/module/cgi.pp new file mode 100644 index 00000000..ce212e97 --- /dev/null +++ b/puppet/modules/apache/manifests/module/cgi.pp @@ -0,0 +1,6 @@ +# enable/disable cgi module +class apache::module::cgi ( $ensure = present ) +{ + +  apache::module { 'cgi': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/dir.pp b/puppet/modules/apache/manifests/module/dir.pp new file mode 100644 index 00000000..da2dc1ee --- /dev/null +++ b/puppet/modules/apache/manifests/module/dir.pp @@ -0,0 +1,6 @@ +# enable/disable dir module +class apache::module::dir ( $ensure = present ) +{ + +  apache::module { 'dir': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/env.pp b/puppet/modules/apache/manifests/module/env.pp new file mode 100644 index 00000000..f358e363 --- /dev/null +++ b/puppet/modules/apache/manifests/module/env.pp @@ -0,0 +1,7 @@ +# install mod_env, needed by api.conf +class apache::module::env ( $ensure = present ) +{ + +  apache::module { 'env': ensure => $ensure } + +} diff --git a/puppet/modules/apache/manifests/module/expires.pp b/puppet/modules/apache/manifests/module/expires.pp new file mode 100644 index 00000000..c56f416b --- /dev/null +++ b/puppet/modules/apache/manifests/module/expires.pp @@ -0,0 +1,5 @@ +# enable/disable expires module +class apache::module::expires ( $ensure = present ) +{ +  apache::module { 'expires': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/headers.pp b/puppet/modules/apache/manifests/module/headers.pp new file mode 100644 index 00000000..d1d587b0 --- /dev/null +++ b/puppet/modules/apache/manifests/module/headers.pp @@ -0,0 +1,6 @@ +# enable/disable headers module +class apache::module::headers ( $ensure = present ) +{ + +  apache::module { 'headers': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/mime.pp b/puppet/modules/apache/manifests/module/mime.pp new file mode 100644 index 00000000..5d691d30 --- /dev/null +++ b/puppet/modules/apache/manifests/module/mime.pp @@ -0,0 +1,6 @@ +# enable/disable mime module +class apache::module::mime ( $ensure = present ) +{ + +  apache::module { 'mime': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/mpm_event.pp b/puppet/modules/apache/manifests/module/mpm_event.pp new file mode 100644 index 00000000..a824cb37 --- /dev/null +++ b/puppet/modules/apache/manifests/module/mpm_event.pp @@ -0,0 +1,7 @@ +# install mod_mpm_event (needed for jessie hosts) +class apache::module::mpm_event ( $ensure = present ) +{ + +  apache::module { 'mpm_event': ensure => $ensure } + +} diff --git a/puppet/modules/apache/manifests/module/mpm_prefork.pp b/puppet/modules/apache/manifests/module/mpm_prefork.pp new file mode 100644 index 00000000..7c08da7f --- /dev/null +++ b/puppet/modules/apache/manifests/module/mpm_prefork.pp @@ -0,0 +1,6 @@ +# enable/disable mpm_prefork module +class apache::module::mpm_prefork ( $ensure = present ) +{ + +  apache::module { 'mpm_prefork': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/negotiation.pp b/puppet/modules/apache/manifests/module/negotiation.pp new file mode 100644 index 00000000..15334fb9 --- /dev/null +++ b/puppet/modules/apache/manifests/module/negotiation.pp @@ -0,0 +1,6 @@ +# enable/disable negotiation module +class apache::module::negotiation ( $ensure = present ) +{ + +  apache::module { 'negotiation': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/php5.pp b/puppet/modules/apache/manifests/module/php5.pp new file mode 100644 index 00000000..ffb571fe --- /dev/null +++ b/puppet/modules/apache/manifests/module/php5.pp @@ -0,0 +1,6 @@ +# enable/disable php5 module +class apache::module::php5 ( $ensure = present ) +{ + +  apache::module { 'php5': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/removeip.pp b/puppet/modules/apache/manifests/module/removeip.pp new file mode 100644 index 00000000..11088fc1 --- /dev/null +++ b/puppet/modules/apache/manifests/module/removeip.pp @@ -0,0 +1,6 @@ +# enable/disable removeip module +class apache::module::removeip ( $ensure = present ) +{ +  package { 'libapache2-mod-removeip': ensure => $ensure } +  apache::module { 'removeip': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/rewrite.pp b/puppet/modules/apache/manifests/module/rewrite.pp new file mode 100644 index 00000000..24ef899b --- /dev/null +++ b/puppet/modules/apache/manifests/module/rewrite.pp @@ -0,0 +1,6 @@ +# enable/disable rewrite module +class apache::module::rewrite ( $ensure = present ) +{ + +  apache::module { 'rewrite': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/socache_shmcb.pp b/puppet/modules/apache/manifests/module/socache_shmcb.pp new file mode 100644 index 00000000..4c53adde --- /dev/null +++ b/puppet/modules/apache/manifests/module/socache_shmcb.pp @@ -0,0 +1,6 @@ +# enable/disable socache_shmcb module +class apache::module::socache_shmcb ( $ensure = present ) +{ + +  apache::module { 'socache_shmcb': ensure => $ensure } +} diff --git a/puppet/modules/apache/manifests/module/status.pp b/puppet/modules/apache/manifests/module/status.pp new file mode 100644 index 00000000..cfc437ca --- /dev/null +++ b/puppet/modules/apache/manifests/module/status.pp @@ -0,0 +1,6 @@ +# enable/disable status module +class apache::module::status ( $ensure = present ) +{ + +  apache::module { 'status': ensure => $present } +} diff --git a/puppet/modules/apache/manifests/mozilla_autoconfig.pp b/puppet/modules/apache/manifests/mozilla_autoconfig.pp new file mode 100644 index 00000000..f16e5ec7 --- /dev/null +++ b/puppet/modules/apache/manifests/mozilla_autoconfig.pp @@ -0,0 +1,37 @@ +# setup autoconfig infos +# +# this will create a global autoconfig file, that maps +# any of your hosted domains on this host to a certain +# provider configuration. Which means, that you get a zero +# setup autoconfig for any domain that you host the website +# and the emails for. +# By default you only need to define the provider, which +# is usually your main domain. Everything else should be +# derived from that. +# You can however still fine tune things from it. +class apache::mozilla_autoconfig( +  $provider, +  $display_name      = undef, +  $shortname         = undef, +  $imap_server       = undef, +  $pop_server        = undef, +  $smtp_server       = undef, +  $documentation_url = undef, +) { +  apache::config::global { 'mozilla_autoconfig.conf': } + +  file{ +    '/var/www/autoconfig': +      ensure  => directory, +      require => Package['apache'], +      owner   => root, +      group   => apache, +      mode    => '0640'; +  '/var/www/autoconfig/config.shtml': +      content => template('apache/webfiles/autoconfig/config.shtml.erb'), +      owner   => root, +      group   => apache, +      mode    => '0640', +      before  => Service['apache'], +  } +} diff --git a/puppet/modules/apache/manifests/munin.pp b/puppet/modules/apache/manifests/munin.pp new file mode 100644 index 00000000..46af1723 --- /dev/null +++ b/puppet/modules/apache/manifests/munin.pp @@ -0,0 +1,12 @@ +# manage apache monitoring things +class apache::munin { +  if $::osfamily == 'Debian' { +    include perl::extensions::libwww +  } + +  munin::plugin{ [ 'apache_accesses', 'apache_processes', 'apache_volume' ]: } +  munin::plugin::deploy { 'apache_activity': +    source  => 'apache/munin/apache_activity', +    seltype => 'munin_services_plugin_exec_t', +  } +} diff --git a/puppet/modules/apache/manifests/noiplog.pp b/puppet/modules/apache/manifests/noiplog.pp new file mode 100644 index 00000000..355d7e6a --- /dev/null +++ b/puppet/modules/apache/manifests/noiplog.pp @@ -0,0 +1,5 @@ +class apache::noiplog { +  apache::config::global{ 'noip_log.conf': +    content => 'LogFormat "127.0.0.1 - - %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %T %V" noip'; +  } +} diff --git a/puppet/modules/apache/manifests/openbsd.pp b/puppet/modules/apache/manifests/openbsd.pp new file mode 100644 index 00000000..96a216ad --- /dev/null +++ b/puppet/modules/apache/manifests/openbsd.pp @@ -0,0 +1,75 @@ +### openbsd +class apache::openbsd inherits apache::base { +  $config_dir = '/var/www' + +  File[vhosts_dir]{ +    path => "${config_dir}/vhosts.d", +  } +  File[modules_dir]{ +    path => "${config_dir}/conf/modules", +  } +  File[config_dir]{ +    path => "${config_dir}/conf.d", +  } +  File[include_dir]{ +    path => "${config_dir}/include.d", +  } +  File['htpasswd_dir']{ +    group => www, +  } +  File[web_dir]{ +    group => daemon, +  } +  file_line{'enable_apache_on_boot': +    path => '/etc/rc.conf.local', +    line => 'httpd flags=""', +  } +  file{'apache_main_config': +    path    => "${config_dir}/conf/httpd.conf", +    source  => ["puppet:///modules/site_apache/config/OpenBSD/${::fqdn}/httpd.conf", +                "puppet:///modules/site_apache/config/OpenBSD/${apache::cluster_node}/httpd.conf", +                'puppet:///modules/site_apache/config/OpenBSD//httpd.conf', +                'puppet:///modules/apache/config/OpenBSD/httpd.conf' ], +    notify  => Service['apache'], +    owner   => root, +    group   => 0, +    mode    => '0644'; +  } +  File[default_apache_index] { +    path => '/var/www/htdocs/default/www/index.html', +  } +  file{'/opt/bin/restart_apache.sh': +    source  => 'puppet:///modules/apache/scripts/OpenBSD/bin/restart_apache.sh', +    require => File['/opt/bin'], +    owner   => root, +    group   => 0, +    mode    => '0700'; +  } + +  ::apache::vhost::webdir{'default': +    datadir => false, +  } + +  Service['apache']{ +    restart => '/opt/bin/restart_apache.sh', +    status  => 'apachectl status', +    start   => 'apachectl start', +    stop    => 'apachectl stop', +  } +  file{'/opt/bin/apache_logrotate.sh': +    source  => 'puppet:///modules/apache/scripts/OpenBSD/bin/apache_logrotate.sh', +    require => File['/opt/bin'], +    owner   => root, +    group   => 0, +    mode    => '0700'; +  } +  cron { 'update_apache_logrotation': +    command => '/bin/sh /opt/bin/apache_logrotate.sh  > /etc/newsyslog_apache.conf', +    minute  => '1', +    hour    => '1', +  } +  cron { 'run_apache_logrotation': +    command => '/usr/bin/newsyslog -f /etc/newsyslog_apache.conf > /dev/null', +    minute  => '10', +  } +} diff --git a/puppet/modules/apache/manifests/package.pp b/puppet/modules/apache/manifests/package.pp new file mode 100644 index 00000000..3308b371 --- /dev/null +++ b/puppet/modules/apache/manifests/package.pp @@ -0,0 +1,32 @@ +# deploy apache as package +class apache::package inherits apache::base { +    package { 'apache': +        name => 'apache', +        ensure => present, +    } +    File['vhosts_dir']{ +        require => Package[apache], +    } +    File['config_dir']{ +        require => Package[apache], +    } +    Service['apache']{ +        require => Package[apache], +    } +    File['default_apache_index']{ +        require => Package[apache], +    } +    File['modules_dir']{ +        require => Package[apache], +    } +    File['include_dir']{ +        require => Package[apache], +    } +    File['web_dir']{ +        require => Package[apache], +    } +    File['htpasswd_dir']{ +        require => Package[apache], +    } +} + diff --git a/puppet/modules/apache/manifests/package/itk.pp b/puppet/modules/apache/manifests/package/itk.pp new file mode 100644 index 00000000..4ca9960e --- /dev/null +++ b/puppet/modules/apache/manifests/package/itk.pp @@ -0,0 +1,5 @@ +class apache::package::itk inherits apache::package { +    Package['apache'] { +        name => 'apache2-itk', +    } +} diff --git a/puppet/modules/apache/manifests/sftponly.pp b/puppet/modules/apache/manifests/sftponly.pp new file mode 100644 index 00000000..ece726b0 --- /dev/null +++ b/puppet/modules/apache/manifests/sftponly.pp @@ -0,0 +1,5 @@ +class apache::sftponly { +  case $::operatingsystem { +    centos: { include apache::sftponly::centos } +  } +} diff --git a/puppet/modules/apache/manifests/sftponly/centos.pp b/puppet/modules/apache/manifests/sftponly/centos.pp new file mode 100644 index 00000000..0f2a43d8 --- /dev/null +++ b/puppet/modules/apache/manifests/sftponly/centos.pp @@ -0,0 +1,10 @@ +# manage sftponly group and apache +# user for access +class apache::sftponly::centos { +  require user::groups::sftponly +  user::groups::manage_user{'apache': +    group   => 'sftponly', +    require => Package['apache'], +    notify  => Service['apache'], +  } +} diff --git a/puppet/modules/apache/manifests/ssl.pp b/puppet/modules/apache/manifests/ssl.pp new file mode 100644 index 00000000..bfef7adc --- /dev/null +++ b/puppet/modules/apache/manifests/ssl.pp @@ -0,0 +1,13 @@ +# manifests/ssl.pp + +class apache::ssl { +  case $::operatingsystem { +    centos: { include apache::ssl::centos } +    openbsd: { include apache::ssl::openbsd } +    debian: { include apache::ssl::debian } +    defaults: { include apache::ssl::base } +  } +  if $apache::manage_shorewall { +    include shorewall::rules::https +  } +} diff --git a/puppet/modules/apache/manifests/ssl/base.pp b/puppet/modules/apache/manifests/ssl/base.pp new file mode 100644 index 00000000..3f329136 --- /dev/null +++ b/puppet/modules/apache/manifests/ssl/base.pp @@ -0,0 +1,15 @@ +# basic defaults for ssl support +class apache::ssl::base ( +) { +  apache::config::include { +    'ssl_defaults.inc': +      content => template('apache/include.d/ssl_defaults.inc.erb'); +  } + +  if !$apache::no_default_site { +    apache::vhost::file{ +      '0-default_ssl': +        content => template('apache/vhosts/0-default_ssl.conf.erb'); +    } +  } +} diff --git a/puppet/modules/apache/manifests/ssl/centos.pp b/puppet/modules/apache/manifests/ssl/centos.pp new file mode 100644 index 00000000..7bc8c895 --- /dev/null +++ b/puppet/modules/apache/manifests/ssl/centos.pp @@ -0,0 +1,12 @@ +class apache::ssl::centos inherits apache::ssl::base { +    package { 'mod_ssl': +        name => 'mod_ssl', +        ensure => present, +        require => Package[apache], +    } +    ::apache::config::global{ 'ssl.conf': } + +    apache::config::global{'00-listen-ssl.conf': +      ensure => absent, +    } +} diff --git a/puppet/modules/apache/manifests/ssl/debian.pp b/puppet/modules/apache/manifests/ssl/debian.pp new file mode 100644 index 00000000..99dfe36e --- /dev/null +++ b/puppet/modules/apache/manifests/ssl/debian.pp @@ -0,0 +1,4 @@ +class apache::ssl::debian inherits apache::ssl::base { +    apache::debian::module { 'ssl': ensure => present } +    apache::config::global { 'ssl.conf': } +} diff --git a/puppet/modules/apache/manifests/ssl/itk.pp b/puppet/modules/apache/manifests/ssl/itk.pp new file mode 100644 index 00000000..5fd3aaf6 --- /dev/null +++ b/puppet/modules/apache/manifests/ssl/itk.pp @@ -0,0 +1,8 @@ +# manifests/ssl/itk.pp + +class apache::ssl::itk inherits apache::ssl { +    case $::operatingsystem { +        centos: { include apache::ssl::itk::centos } +    } +} + diff --git a/puppet/modules/apache/manifests/ssl/itk/centos.pp b/puppet/modules/apache/manifests/ssl/itk/centos.pp new file mode 100644 index 00000000..fb6a4a6b --- /dev/null +++ b/puppet/modules/apache/manifests/ssl/itk/centos.pp @@ -0,0 +1,6 @@ +class apache::ssl::itk::centos inherits apache::ssl::centos { +    Package['mod_ssl']{ +        name => 'mod_ssl-itk', +    } +} + diff --git a/puppet/modules/apache/manifests/ssl/itk_plus.pp b/puppet/modules/apache/manifests/ssl/itk_plus.pp new file mode 100644 index 00000000..0c8e6679 --- /dev/null +++ b/puppet/modules/apache/manifests/ssl/itk_plus.pp @@ -0,0 +1,6 @@ +class apache::ssl::itk_plus inherits apache::ssl::itk { +    case $::operatingsystem { +        centos: { include ::apache::ssl::itk_plus::centos } +        default: { fail("itk plus mode is currently only implemented for CentOS") } +    } +} diff --git a/puppet/modules/apache/manifests/ssl/itk_plus/centos.pp b/puppet/modules/apache/manifests/ssl/itk_plus/centos.pp new file mode 100644 index 00000000..00fb4729 --- /dev/null +++ b/puppet/modules/apache/manifests/ssl/itk_plus/centos.pp @@ -0,0 +1,11 @@ +class apache::ssl::itk_plus::centos inherits apache::ssl::centos { +  include apache::ssl::itk::centos +  Apache::Config::Global['ssl.conf']{ +    source => "modules/apache/itk_plus/conf.d/${::operatingsystem}/ssl.conf", +  } + +  Apache::Config::Global['00-listen-ssl.conf']{ +    ensure => 'present', +    content => template("apache/itk_plus/${::operatingsystem}/00-listen-ssl.conf.erb"), +  } +} diff --git a/puppet/modules/apache/manifests/ssl/openbsd.pp b/puppet/modules/apache/manifests/ssl/openbsd.pp new file mode 100644 index 00000000..43bc6803 --- /dev/null +++ b/puppet/modules/apache/manifests/ssl/openbsd.pp @@ -0,0 +1,18 @@ +class apache::ssl::openbsd inherits apache::openbsd { +    include apache::ssl::base + +    File_line['enable_apache_on_boot']{ +        ensure => 'absent', +    } +    file_line{'enable_apachessl_on_boot': +        path => '/etc/rc.conf.local', +        line => 'httpd flags="-DSSL"', +    } + +    File['/opt/bin/restart_apache.sh']{ +        source => "puppet:///modules/apache/scripts/OpenBSD/bin/restart_apache_ssl.sh", +    } +    Service['apache']{ +        start => 'apachectl startssl', +    } +} diff --git a/puppet/modules/apache/manifests/status.pp b/puppet/modules/apache/manifests/status.pp new file mode 100644 index 00000000..c5070130 --- /dev/null +++ b/puppet/modules/apache/manifests/status.pp @@ -0,0 +1,13 @@ +# enable apache status page +# manage munin plugins if requested +class apache::status { +  case $::operatingsystem { +    centos: { include apache::status::centos } +    debian: { include apache::status::debian } +    defaults: { include apache::status::base } +  } +  if $apache::manage_munin { +    include apache::munin +  } +} + diff --git a/puppet/modules/apache/manifests/status/base.pp b/puppet/modules/apache/manifests/status/base.pp new file mode 100644 index 00000000..df6c90b9 --- /dev/null +++ b/puppet/modules/apache/manifests/status/base.pp @@ -0,0 +1 @@ +class apache::status::base {} diff --git a/puppet/modules/apache/manifests/status/centos.pp b/puppet/modules/apache/manifests/status/centos.pp new file mode 100644 index 00000000..d893707d --- /dev/null +++ b/puppet/modules/apache/manifests/status/centos.pp @@ -0,0 +1,5 @@ +### centos +class apache::status::centos { +    ::apache::config::global{ 'status.conf': } +} + diff --git a/puppet/modules/apache/manifests/status/debian.pp b/puppet/modules/apache/manifests/status/debian.pp new file mode 100644 index 00000000..222b85c7 --- /dev/null +++ b/puppet/modules/apache/manifests/status/debian.pp @@ -0,0 +1,4 @@ +# enable status module on debian +class apache::status::debian { +  ::apache::debian::module { 'status': } +} diff --git a/puppet/modules/apache/manifests/vhost.pp b/puppet/modules/apache/manifests/vhost.pp new file mode 100644 index 00000000..da1ce901 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost.pp @@ -0,0 +1,127 @@ +# this is a wrapper for apache::vhost::file and avhost::template below +# +# vhost_mode: which option is choosed to deploy the vhost +#   - template: generate it from a template (default) +#   - file: deploy a vhost file (apache::vhost::file will be called directly) +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +# +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: (*default*) don't activate mod_security +#    - true: activate mod_security +# +define apache::vhost( +    $ensure                           = present, +    $configuration                    = {}, +    $path                             = 'absent', +    $path_is_webdir                   = false, +    $logpath                          = 'absent', +    $logmode                          = 'default', +    $logprefix                        = '', +    $vhost_mode                       = 'template', +    $template_partial                 = 'apache/vhosts/static/partial.erb', +    $vhost_source                     = 'absent', +    $vhost_destination                = 'absent', +    $content                          = 'absent', +    $domain                           = 'absent', +    $domainalias                      = 'absent', +    $server_admin                     = 'absent', +    $allow_override                   = 'None', +    $php_settings                     = {}, +    $php_options                      = {}, +    $cgi_binpath                      = 'absent', +    $default_charset                  = 'absent', +    $do_includes                      = false, +    $options                          = 'absent', +    $additional_options               = 'absent', +    $run_mode                         = 'normal', +    $run_uid                          = 'absent', +    $run_gid                          = 'absent', +    $ssl_mode                         = false, +    $htpasswd_file                    = 'absent', +    $htpasswd_path                    = 'absent', +    $mod_security                     = true, +    $mod_security_relevantonly        = true, +    $mod_security_rules_to_disable    = [], +    $mod_security_additional_options  = 'absent', +    $use_mod_macro                    = false, +    $ldap_auth                        = false, +    $ldap_user                        = 'any', +    $passing_extension                = 'absent', +    $gempath                          = 'absent' +) { +    # file or template mode? +    case $vhost_mode { +        'file': { +            apache::vhost::file{$name: +                ensure            => $ensure, +                configuration     => $configuration, +                vhost_source      => $vhost_source, +                vhost_destination => $vhost_destination, +                do_includes       => $do_includes, +                run_mode          => $run_mode, +                mod_security      => $mod_security, +                htpasswd_file     => $htpasswd_file, +                htpasswd_path     => $htpasswd_path, +                use_mod_macro     => $use_mod_macro, +            } +        } +        'template': { +            apache::vhost::template{$name: +                ensure                          => $ensure, +                configuration                   => $configuration, +                path                            => $path, +                path_is_webdir                  => $path_is_webdir, +                logpath                         => $logpath, +                logmode                         => $logmode, +                logprefix                       => $logprefix, +                domain                          => $domain, +                domainalias                     => $domainalias, +                server_admin                    => $server_admin, +                cgi_binpath                     => $cgi_binpath, +                allow_override                  => $allow_override, +                do_includes                     => $do_includes, +                options                         => $options, +                additional_options              => $additional_options, +                default_charset                 => $default_charset, +                php_settings                    => $php_settings, +                php_options                     => $php_options, +                run_mode                        => $run_mode, +                run_uid                         => $run_uid, +                run_gid                         => $run_gid, +                template_partial                => $template_partial, +                ssl_mode                        => $ssl_mode, +                htpasswd_file                   => $htpasswd_file, +                htpasswd_path                   => $htpasswd_path, +                ldap_auth                       => $ldap_auth, +                ldap_user                       => $ldap_user, +                mod_security                    => $mod_security, +                mod_security_relevantonly       => $mod_security_relevantonly, +                mod_security_rules_to_disable   => $mod_security_rules_to_disable, +                mod_security_additional_options => $mod_security_additional_options, +                use_mod_macro                   => $use_mod_macro, +                passing_extension               => $passing_extension, +                gempath                         => $gempath, +            } +        } +        default: { fail("No such vhost_mode: ${vhost_mode} defined for ${name}.") } +    } +} diff --git a/puppet/modules/apache/manifests/vhost/davdbdir.pp b/puppet/modules/apache/manifests/vhost/davdbdir.pp new file mode 100644 index 00000000..459167c9 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/davdbdir.pp @@ -0,0 +1,40 @@ +define apache::vhost::davdbdir( +    $ensure = present, +    $dav_db_dir = 'absent', +    $documentroot_owner = apache, +    $documentroot_group = 0, +    $documentroot_mode = 0750, +    $run_mode = 'normal', +    $run_uid = 'absent' +){ +    # php db dir +    case $dav_db_dir { +        'absent': { +            include apache::defaultdavdbdir +            $real_dav_db_dir = "/var/www/dav_db_dir/${name}" +        } +        default: { $real_dav_db_dir = $dav_db_dir } +    } + +    case $ensure { +        absent: { +            file{$real_dav_db_dir: +                ensure => absent, +                purge => true, +                force => true, +                recurse => true, +            } +        } +        default: { +            file{$real_dav_db_dir: +                ensure => directory, +                owner => $run_mode ? { +                    'itk' => $run_uid, +                    default => $documentroot_owner +                }, +                group => $documentroot_group, mode => $documentroot_mode; +            } +        } +    } +} + diff --git a/puppet/modules/apache/manifests/vhost/file.pp b/puppet/modules/apache/manifests/vhost/file.pp new file mode 100644 index 00000000..686cb1a1 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/file.pp @@ -0,0 +1,151 @@ +# htpasswd_file: wether to deploy a passwd for this vhost or not +#   - absent: ignore (default) +#   - nodeploy: htpasswd file isn't deployed by this mechanism +#   - else: try to deploy the file +# +# htpasswd_path: where to deploy the passwd file +#   - absent: standardpath (default) +#   - else: path to deploy +# +# ssl_mode: wether this vhost supports ssl or not +#   - false: don't enable ssl for this vhost (default) +#   - true: enable ssl for this vhost +#   - force: enable ssl and redirect non-ssl to ssl +#   - only: enable ssl only +# +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +# +# +# mod_security: Whether we use mod_security or not +#               (will include mod_security module) +#    - false: (*default*) don't activate mod_security +#    - true: activate mod_security +# +define apache::vhost::file( +    $ensure             = present, +    $configuration      = {}, +    $vhost_source       = 'absent', +    $vhost_destination  = 'absent', +    $content            = 'absent', +    $do_includes        = false, +    $run_mode           = 'normal', +    $logmode            = 'default', +    $ssl_mode           = false, +    $mod_security       = false, +    $htpasswd_file      = 'absent', +    $htpasswd_path      = 'absent', +    $use_mod_macro      = false +){ +    $vhosts_dir = $::operatingsystem ? { +        centos  => "${apache::centos::config_dir}/vhosts.d", +        gentoo  => "${apache::gentoo::config_dir}/vhosts.d", +        debian  => "${apache::debian::config_dir}/sites-enabled", +        ubuntu  => "${apache::ubuntu::config_dir}/sites-enabled", +        openbsd => "${apache::openbsd::config_dir}/vhosts.d", +        default => '/etc/apache2/vhosts.d', +    } +    $real_vhost_destination = $vhost_destination ? { +        'absent'  => "${vhosts_dir}/${name}.conf", +        default   => $vhost_destination, +    } +    file{"${name}.conf": +        ensure  => $ensure, +        path    => $real_vhost_destination, +        require => File[vhosts_dir], +        notify  => Service[apache], +        owner   => root, +        group   => 0, +        mode    => '0644'; +    } +    if $ensure != 'absent' { +      if $do_includes { +        include ::apache::includes +      } +      if $use_mod_macro { +        include ::apache::mod_macro +      } +      case $logmode { +        'semianonym','anonym': { include apache::noiplog } +      } +      case $run_mode { +        'itk': { +          include ::apache::itk::lock +          if $mod_security { include mod_security::itk } +        } +        'proxy-itk','static-itk': { +          include ::apache::itk_plus::lock +          if $mod_security { include mod_security::itk_plus } +        } +        default: { +          if $mod_security { include mod_security } +        } +      } + +      case $content { +        'absent': { +            $real_vhost_source = $vhost_source ? { +                'absent'  => [ +                    "puppet:///modules/site_apache/vhosts.d/${::fqdn}/${name}.conf", +                    "puppet:///modules/site_apache/vhosts.d/${apache::cluster_node}/${name}.conf", +                    "puppet:///modules/site_apache/vhosts.d/${::operatingsystem}.${::operatingsystemmajrelease}/${name}.conf", +                    "puppet:///modules/site_apache/vhosts.d/${::operatingsystem}/${name}.conf", +                    "puppet:///modules/site_apache/vhosts.d/${name}.conf", +                    "puppet:///modules/apache/vhosts.d/${::operatingsystem}.${::operatingsystemmajrelease}/${name}.conf", +                    "puppet:///modules/apache/vhosts.d/${::operatingsystem}/${name}.conf", +                    "puppet:///modules/apache/vhosts.d/${name}.conf" +                ], +                default => "puppet:///${vhost_source}", +            } +            File["${name}.conf"]{ +                source => $real_vhost_source, +            } +        } +        default: { +            File["${name}.conf"]{ +                content => $content, +            } +        } +      } +    } +    case $htpasswd_file { +        'absent','nodeploy': { info("don't deploy a htpasswd file for ${name}") } +        default: { +            if $htpasswd_path == 'absent' { +                $real_htpasswd_path = "/var/www/htpasswds/${name}" +            } else { +                $real_htpasswd_path = $htpasswd_path +            } +            file{$real_htpasswd_path: +                ensure => $ensure, +            } +            if ($ensure!='absent') { +              File[$real_htpasswd_path]{ +                source  => [ "puppet:///modules/site_apache/htpasswds/${::fqdn}/${name}", +                            "puppet:///modules/site_apache/htpasswds/${apache::cluster_node}/${name}", +                            "puppet:///modules/site_apache/htpasswds/${name}" ], +                owner   => root, +                group   => 0, +                mode    => '0644', +              } +            } +        } +    } +} + diff --git a/puppet/modules/apache/manifests/vhost/file/documentrootdir.pp b/puppet/modules/apache/manifests/vhost/file/documentrootdir.pp new file mode 100644 index 00000000..425406ad --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/file/documentrootdir.pp @@ -0,0 +1,24 @@ +define apache::vhost::file::documentrootdir( +      $ensure = directory, +      $documentroot, +      $filename, +      $thedomain, +      $owner = 'root', +      $group = '0', +      $mode = 440 +){ +  file{"$documentroot/$filename": +    require => Apache::Vhost::Webdir["$thedomain"], +    owner => $owner, group => $group, mode => $mode; +  } +  if $ensure != 'absent' { +    File["$documentroot/$filename"]{ +      ensure => directory, +    } +  } else { +    File["$documentroot/$filename"]{ +      ensure => $ensure, +    } +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/file/documentrootfile.pp b/puppet/modules/apache/manifests/vhost/file/documentrootfile.pp new file mode 100644 index 00000000..c5bc72a1 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/file/documentrootfile.pp @@ -0,0 +1,27 @@ +# place a file in the documentroot +define apache::vhost::file::documentrootfile( +  $documentroot, +  $filename, +  $thedomain, +  $owner        = 'root', +  $group        = '0', +  $mode         = '0440', +){ +    file{"${documentroot}/${filename}": +        source  => [ "puppet:///modules/site_apache/vhost_varieties/${::fqdn}/${thedomain}/${filename}", +                    "puppet:///modules/site_apache/vhost_varieties/${apache::cluster_node}/${thedomain}/${filename}", +                    "puppet:///modules/site_apache/vhost_varieties/${::operatingsystem}.${::operatingsystemmajrelease}/${thedomain}/${filename}", +                    "puppet:///modules/site_apache/vhost_varieties/${::operatingsystem}/${thedomain}/${filename}", +                    "puppet:///modules/site_apache/vhost_varieties/${thedomain}/${filename}", +                    "puppet:///modules/apache/vhost_varieties/${thedomain}/${filename}", +                    "puppet:///modules/apache/vhost_varieties/${::operatingsystem}.${::operatingsystemmajrelease}/${thedomain}/${filename}", +                    "puppet:///modules/apache/vhost_varieties/${::operatingsystem}/${thedomain}/${filename}", +                    "puppet:///modules/apache/vhost_varieties/${thedomain}/${filename}", +        ], +        require => Apache::Vhost::Webdir[$thedomain], +        owner   => $owner, +        group   => $group, +        mode    => $mode; +    } +} + diff --git a/puppet/modules/apache/manifests/vhost/gitweb.pp b/puppet/modules/apache/manifests/vhost/gitweb.pp new file mode 100644 index 00000000..6dd86439 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/gitweb.pp @@ -0,0 +1,59 @@ +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +# +define apache::vhost::gitweb( +    $ensure = present, +    $configuration = {}, +    $domain = 'absent', +    $logmode = 'default', +    $domainalias = 'absent', +    $server_admin = 'absent', +    $owner = root, +    $group = apache, +    $documentroot_owner = apache, +    $documentroot_group = 0, +    $documentroot_mode = 0640, +    $allow_override = 'None', +    $template_partial = 'apache/vhosts/gitweb/partial.erb', +    $do_includes = false, +    $options = 'absent', +    $additional_options = 'absent', +    $default_charset = 'absent', +    $ssl_mode = false, +    $htpasswd_file = 'absent', +    $htpasswd_path = 'absent' +){ +    # create vhost configuration file +    ::apache::vhost{$name: +        ensure => $ensure, +        configuration => $configuration, +        path => '/var/www/git', +        path_is_webdir => true, +        logpath => $::operatingsystem ? { +            centos => '/var/log/httpd', +            fedora => '/var/log/httpd', +            redhat => '/var/log/httpd', +            openbsd => '/var/www/logs', +            default => '/var/log/apache2' +        }, +        logmode => $logmode, +        template_partial => $template_partial, +        domain => $domain, +        domainalias => $domainalias, +        server_admin => $server_admin, +        allow_override => $allow_override, +        do_includes => $do_includes, +        options => $options, +        additional_options => $additional_options, +        default_charset => $default_charset, +        run_mode => 'normal', +        ssl_mode => $ssl_mode, +        htpasswd_file => $htpasswd_file, +        htpasswd_path => $htpasswd_path, +        mod_security => false, +    } +} + diff --git a/puppet/modules/apache/manifests/vhost/modperl.pp b/puppet/modules/apache/manifests/vhost/modperl.pp new file mode 100644 index 00000000..31e46b6f --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/modperl.pp @@ -0,0 +1,153 @@ +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +# +define apache::vhost::modperl( +    $ensure = present, +    $configuration = configuration, +    $domain = 'absent', +    $domainalias = 'absent', +    $server_admin = 'absent', +    $logmode = 'default', +    $path = 'absent', +    $owner = root, +    $group = apache, +    $documentroot_owner = apache, +    $documentroot_group = 0, +    $documentroot_mode = 0640, +    $run_mode = 'normal', +    $run_uid = 'absent', +    $run_gid = 'absent', +    $allow_override = 'None', +    $cgi_binpath = 'absent', +    $do_includes = false, +    $options = 'absent', +    $additional_options = 'absent', +    $default_charset = 'absent', +    $mod_security = true, +    $mod_security_relevantonly = true, +    $mod_security_rules_to_disable = [], +    $mod_security_additional_options = 'absent', +    $ssl_mode = false, +    $vhost_mode = 'template', +    $template_partial = 'apache/vhosts/perl/partial.erb', +    $vhost_source = 'absent', +    $vhost_destination = 'absent', +    $htpasswd_file = 'absent', +    $htpasswd_path = 'absent' +){ +    # cgi_bin path +    case $cgi_binpath { +        'absent': { +            $real_path = $path ? { +                'absent' => $::operatingsystem ? { +                    openbsd => "/var/www/htdocs/${name}", +                    default => "/var/www/vhosts/${name}" +                }, +                default => $path +            } +            $real_cgi_binpath = "${real_path}/cgi-bin" +        } +        default: { $real_cgi_binpath = $cgi_binpath } +    } + +    file{$real_cgi_binpath: +        ensure => $ensure ? { +          'absent' => 'absent', +          default => directory +        }, +        owner => $documentroot_owner, +        group => $documentroot_group, +        mode => $documentroot_mode; +    } + +    if $ensure != 'absent' { +      case $run_mode { +        'proxy-itk','static-itk': { +          include ::mod_perl::itk_plus +        } +        'fcgid': { +          include ::mod_fcgid +          include apache::include::mod_fcgid + +          # we don't need mod_perl if we run it as fcgid +          include ::mod_perl::disable +          mod_fcgid::starter {$name: +            cgi_type => 'perl', +            owner => $run_uid, +            group => $run_gid, +            notify => Service['apache'], +          } +        } +        default: { include ::mod_perl } +      } +    } + +    # create webdir +    ::apache::vhost::webdir{$name: +        ensure => $ensure, +        path => $path, +        owner => $owner, +        group => $group, +        run_mode => $run_mode, +        documentroot_owner => $documentroot_owner, +        documentroot_group => $documentroot_group, +        documentroot_mode => $documentroot_mode, +    } + +    # create vhost configuration file +    ::apache::vhost{$name: +        ensure => $ensure, +        configuration => $configuration, +        path => $path, +        logmode => $logmode, +        vhost_mode => $vhost_mode, +        template_partial => $template_partial, +        vhost_source => $vhost_source, +        vhost_destination => $vhost_destination, +        domain => $domain, +        domainalias => $domainalias, +        server_admin => $server_admin, +        run_mode => $run_mode, +        run_uid => $run_uid, +        run_gid => $run_gid, +        allow_override => $allow_override, +        do_includes => $do_includes, +        options => $options, +        additional_options => $additional_options, +        default_charset => $default_charset, +        cgi_binpath => $real_cgi_binpath, +        ssl_mode => $ssl_mode, +        htpasswd_file => $htpasswd_file, +        htpasswd_path => $htpasswd_path, +        mod_security => $mod_security, +        mod_security_relevantonly => $mod_security_relevantonly, +        mod_security_rules_to_disable => $mod_security_rules_to_disable, +        mod_security_additional_options => $mod_security_additional_options, +        passing_extension => 'pl' +    } +} + diff --git a/puppet/modules/apache/manifests/vhost/passenger.pp b/puppet/modules/apache/manifests/vhost/passenger.pp new file mode 100644 index 00000000..46218908 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/passenger.pp @@ -0,0 +1,139 @@ +# run_uid: the uid the vhost should run as with the mod_passenger module +# run_gid: the gid the vhost should run as with the mod_passenger module +# +# logmode: +# +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: don't activate mod_security +#    - true: (*defaul*) activate mod_security +# +define apache::vhost::passenger( +    $ensure = present, +    $configuration = {}, +    $domain = 'absent', +    $domainalias = 'absent', +    $server_admin = 'absent', +    $logmode = 'default', +    $path = 'absent', +    $manage_webdir = true, +    $manage_docroot = true, +    $owner = root, +    $group = apache, +    $documentroot_owner = apache, +    $documentroot_group = 0, +    $documentroot_mode = 0640, +    $run_uid = 'absent', +    $run_gid = 'absent', +    $allow_override = 'None', +    $do_includes = false, +    $options = 'absent', +    $additional_options = 'absent', +    $default_charset = 'absent', +    $mod_security = true, +    $mod_security_relevantonly = true, +    $mod_security_rules_to_disable = [], +    $mod_security_additional_options = 'absent', +    $ssl_mode = false, +    $vhost_mode = 'template', +    $template_partial = 'apache/vhosts/passenger/partial.erb', +    $vhost_source = 'absent', +    $vhost_destination = 'absent', +    $htpasswd_file = 'absent', +    $htpasswd_path = 'absent', +    $passenger_ree = false, +    $passenger_app = 'rails' +){ + +    if $passenger_ree { +      include ::passenger::ree::apache +    } else { +      include ::passenger::apache +    } + +    if $manage_webdir { +      # create webdir +      ::apache::vhost::webdir{$name: +        ensure => $ensure, +        path => $path, +        owner => $owner, +        group => $group, +        mode => 0644, +        run_mode => 'normal', +        manage_docroot => $manage_docroot, +        documentroot_owner => $documentroot_owner, +        documentroot_group => $run_gid, +        documentroot_mode => $documentroot_mode, +      } +    } +    $real_path = $path ? { +        'absent' => $::operatingsystem ? { +            openbsd => "/var/www/htdocs/${name}", +            default => "/var/www/vhosts/${name}" +        }, +        default => $path +    } +    file{ +      ["${real_path}/www/tmp", "${real_path}/www/log"]: +        ensure => directory, +        owner => $documentroot_owner, group => $run_gid, mode => 0660; +      ["${real_path}/www/public", "${real_path}/gems"]: +        ensure => directory, +        owner => $documentroot_owner, group => $run_gid, mode => 0640; +    } +    if $passenger_app == 'rails' { +      file{ +        "${real_path}/www/config": +          ensure => directory, +          owner => $documentroot_owner, group => $run_gid, mode => 0640; +        "${real_path}/www/config/environment.rb": +          ensure => present, +          owner => $run_uid, group => $run_gid, mode => 0640; +      } +    } else { +      #rack based +      file{ +        "${real_path}/www/config.ru": +          ensure => present, +          owner => $run_uid, group => $run_gid, mode => 0640; +      } +    } + +    # create vhost configuration file +    ::apache::vhost{$name: +        ensure => $ensure, +        configuration => $configuration, +        path => "${real_path}/www/public", +        path_is_webdir => true, +        template_partial => $template_partial, +        logmode => $logmode, +        logpath => "${real_path}/logs", +        vhost_mode => $vhost_mode, +        vhost_source => $vhost_source, +        vhost_destination => $vhost_destination, +        domain => $domain, +        domainalias => $domainalias, +        server_admin => $server_admin, +        run_mode => 'normal', +        run_uid => $run_uid, +        run_gid => $run_gid, +        allow_override => $allow_override, +        do_includes => $do_includes, +        options => $options, +        additional_options => $additional_options, +        default_charset => $default_charset, +        ssl_mode => $ssl_mode, +        htpasswd_file => $htpasswd_file, +        htpasswd_path => $htpasswd_path, +        mod_security => $mod_security, +        mod_security_relevantonly => $mod_security_relevantonly, +        mod_security_rules_to_disable => $mod_security_rules_to_disable, +        mod_security_additional_options => $mod_security_additional_options, +        gempath => "${real_path}/gems" +    } +} + diff --git a/puppet/modules/apache/manifests/vhost/php/drupal.pp b/puppet/modules/apache/manifests/vhost/php/drupal.pp new file mode 100644 index 00000000..5b15e6a0 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/drupal.pp @@ -0,0 +1,144 @@ +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +# php_safe_mode_exec_bins: An array of local binaries which should be linked in the +#                          safe_mode_exec_bin for this hosting +#                          *default*: None +# php_default_charset: default charset header for php. +#                      *default*: absent, which will set the same as default_charset +#                                 of apache +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +# +define apache::vhost::php::drupal( +  $ensure                           = present, +  $configuration                    = {}, +  $domain                           = 'absent', +  $domainalias                      = 'absent', +  $server_admin                     = 'absent', +  $logmode                          = 'default', +  $path                             = 'absent', +  $owner                            = root, +  $group                            = apache, +  $documentroot_owner               = apache, +  $documentroot_group               = 0, +  $documentroot_mode                = '0640', +  $run_mode                         = 'normal', +  $run_uid                          = 'absent', +  $run_gid                          = 'absent', +  $allow_override                   = 'None', +  $php_settings                     = {}, +  $php_options                      = {}, +  $do_includes                      = false, +  $options                          = 'absent', +  $additional_options               = 'absent', +  $default_charset                  = 'absent', +  $mod_security                     = true, +  $mod_security_relevantonly        = true, +  $mod_security_rules_to_disable    = [], +  $mod_security_additional_options  = 'absent', +  $ssl_mode                         = false, +  $vhost_mode                       = 'template', +  $template_partial                 = 'apache/vhosts/php_drupal/partial.erb', +  $vhost_source                     = 'absent', +  $vhost_destination                = 'absent', +  $htpasswd_file                    = 'absent', +  $htpasswd_path                    = 'absent', +  $manage_directories               = true, +  $config_webwriteable              = false, +  $manage_config                    = true, +  $manage_cron                      = true +){ +  $documentroot = $path ? { +      'absent' => $::operatingsystem ? { +          openbsd => "/var/www/htdocs/${name}/www", +          default => "/var/www/vhosts/${name}/www" +      }, +      default => "${path}/www" +  } + +  if $manage_cron { +    if $domain == 'absent' { +      $real_domain = $name +    } else { +      $real_domain = $domain +    } + +    file{"/etc/cron.d/drupal_cron_${name}": +      content => "0   *   *   *   *   apache wget -O - -q -t 1 http://${real_domain}/cron.php\n", +      owner   => root, +      group   => 0, +      mode    => '0644'; +    } +  } + +  $std_drupal_php_settings = { +    magic_quotes_gpc                => 0, +    register_globals                => 0, +    'session.auto_start'            => 0, +    'mbstring.http_input'           => 'pass', +    'mbstring.http_output'          => 'pass', +    'mbstring.encoding_translation' => 0, +  } + +  # create vhost configuration file +  ::apache::vhost::php::webapp{$name: +    ensure                          => $ensure, +    configuration                   => $configuration, +    domain                          => $domain, +    domainalias                     => $domainalias, +    server_admin                    => $server_admin, +    logmode                         => $logmode, +    path                            => $path, +    owner                           => $owner, +    group                           => $group, +    documentroot_owner              => $documentroot_owner, +    documentroot_group              => $documentroot_group, +    documentroot_mode               => $documentroot_mode, +    run_mode                        => $run_mode, +    run_uid                         => $run_uid, +    run_gid                         => $run_gid, +    allow_override                  => $allow_override, +    php_settings                    => merge($std_drupal_php_settings, $php_settings), +    php_options                     => $php_options, +    do_includes                     => $do_includes, +    options                         => $options, +    additional_options              => $additional_options, +    default_charset                 => $default_charset, +    mod_security                    => $mod_security, +    mod_security_relevantonly       => $mod_security_relevantonly, +    mod_security_rules_to_disable   => $mod_security_rules_to_disable, +    mod_security_additional_options => $mod_security_additional_options, +    ssl_mode                        => $ssl_mode, +    vhost_mode                      => $vhost_mode, +    template_partial                => $template_partial, +    vhost_source                    => $vhost_source, +    vhost_destination               => $vhost_destination, +    htpasswd_file                   => $htpasswd_file, +    htpasswd_path                   => $htpasswd_path, +    manage_directories              => false, +    manage_config                   => false, +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/php/gallery2.pp b/puppet/modules/apache/manifests/vhost/php/gallery2.pp new file mode 100644 index 00000000..3acb011d --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/gallery2.pp @@ -0,0 +1,141 @@ +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: (*defaul*) don't activate mod_security +#    - true: activate mod_security +# +# php_safe_mode_exec_bins: An array of local binaries which should be linked in the +#                          safe_mode_exec_bin for this hosting +#                          *default*: None +# php_default_charset: default charset header for php. +#                      *default*: absent, which will set the same as default_charset +#                                 of apache +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +define apache::vhost::php::gallery2( +  $ensure                           = present, +  $configuration                    = {}, +  $domain                           = 'absent', +  $domainalias                      = 'absent', +  $server_admin                     = 'absent', +  $logmode                          = 'default', +  $path                             = 'absent', +  $owner                            = root, +  $group                            = apache, +  $documentroot_owner               = apache, +  $documentroot_group               = 0, +  $documentroot_mode                = 0640, +  $run_mode                         = 'normal', +  $run_uid                          = 'absent', +  $run_gid                          = 'absent', +  $allow_override                   = 'None', +  $php_settings                     = {}, +  $php_options                      = {}, +  $do_includes                      = false, +  $options                          = 'absent', +  $additional_options               = 'absent', +  $default_charset                  = 'absent', +  $mod_security                     = false, +  $mod_security_relevantonly        = true, +  $mod_security_rules_to_disable    = [], +  $mod_security_additional_options  = 'absent', +  $ssl_mode                         = false, +  $vhost_mode                       = 'template', +  $template_partial                 = 'apache/vhosts/php_gallery2/partial.erb', +  $vhost_source                     = 'absent', +  $vhost_destination                = 'absent', +  $htpasswd_file                    = 'absent', +  $htpasswd_path                    = 'absent', +  $manage_config                    = true, +  $config_webwriteable              = false, +  $manage_directories               = true, +){ +  $documentroot = $path ? { +    'absent' => $::operatingsystem ? { +      openbsd => "/var/www/htdocs/${name}/www", +      default => "/var/www/vhosts/${name}/www" +    }, +    default => "${path}/www" +  } +  $upload_dir = "/var/www/vhosts/${name}/data/upload" +  $gdata_dir = "/var/www/vhosts/${name}/data/gdata" +  if $ensure != 'absent' { +    file{ +      $gdata_dir: +        ensure  => 'directory', +        owner   => $documentroot_owner, +        group   => $documentroot_group, +        mode    => '0660'; +      $upload_dir: +        ensure  => 'directory', +        owner   => $documentroot_owner, +        group   => $documentroot_group, +        mode    => '0660'; +    } +  } + +  $gallery_php_settings = { +    safe_mode        => 'Off', +    output_buffering => 'Off', +  } +  $real_php_settings = merge($gallery_php_settings,$php_settings) + +  # create vhost configuration file +  ::apache::vhost::php::webapp{$name: +    ensure                          => $ensure, +    configuration                   => $configuration, +    domain                          => $domain, +    domainalias                     => $domainalias, +    server_admin                    => $server_admin, +    logmode                         => $logmode, +    path                            => $path, +    owner                           => $owner, +    group                           => $group, +    documentroot_owner              => $documentroot_owner, +    documentroot_group              => $documentroot_group, +    documentroot_mode               => $documentroot_mode, +    run_mode                        => $run_mode, +    run_uid                         => $run_uid, +    run_gid                         => $run_gid, +    allow_override                  => $allow_override, +    php_settings                    => $real_php_settings, +    php_options                     => $php_options, +    do_includes                     => $do_includes, +    options                         => $options, +    additional_options              => $additional_options, +    default_charset                 => $default_charset, +    mod_security                    => $mod_security, +    mod_security_relevantonly       => $mod_security_relevantonly, +    mod_security_rules_to_disable   => $mod_security_rules_to_disable, +    mod_security_additional_options => $mod_security_additional_options, +    ssl_mode                        => $ssl_mode, +    vhost_mode                      => $vhost_mode, +    template_partial                => $template_partial, +    vhost_source                    => $vhost_source, +    vhost_destination               => $vhost_destination, +    htpasswd_file                   => $htpasswd_file, +    htpasswd_path                   => $htpasswd_path, +    manage_directories              => $manage_directories, +    manage_config                   => $manage_config, +    config_file                     => 'config.php', +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/php/global_exec_bin_dir.pp b/puppet/modules/apache/manifests/vhost/php/global_exec_bin_dir.pp new file mode 100644 index 00000000..efcdaf7f --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/global_exec_bin_dir.pp @@ -0,0 +1,9 @@ +# manage global exec_bin_dir +class apache::vhost::php::global_exec_bin_dir { +  file{'/var/www/php_safe_exec_bins': +    ensure  => directory, +    owner   => root, +    group   => apache, +    mode    => '0640'; +  } +} diff --git a/puppet/modules/apache/manifests/vhost/php/joomla.pp b/puppet/modules/apache/manifests/vhost/php/joomla.pp new file mode 100644 index 00000000..ed0696f8 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/joomla.pp @@ -0,0 +1,174 @@ +# run_mode: controls in which mode the vhost should be run, there are different +#           setups possible: +#   - normal: (*default*) run vhost with the current active worker +#             (default: prefork) don't setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in +#          combination with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just +#                proxies all the requests for the itk setup, that listens only +#                on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk +#                setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves +#                 all the static +#                 content and proxies the dynamic calls to the itk setup, that +#                 listens only on the loobpack device +#                 (Incompatibility: cannot be used in combination with 'itk' +#                 mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security +#               module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +define apache::vhost::php::joomla( +  $ensure                           = present, +  $configuration                    = {}, +  $domain                           = 'absent', +  $domainalias                      = 'absent', +  $server_admin                     = 'absent', +  $logmode                          = 'default', +  $path                             = 'absent', +  $owner                            = root, +  $group                            = apache, +  $documentroot_owner               = apache, +  $documentroot_group               = 0, +  $documentroot_mode                = '0640', +  $run_mode                         = 'normal', +  $run_uid                          = 'absent', +  $run_gid                          = 'absent', +  $allow_override                   = 'None', +  $php_settings                     = {}, +  $php_options                      = {}, +  $php_installation                 = 'system', +  $do_includes                      = false, +  $options                          = 'absent', +  $additional_options               = 'absent', +  $default_charset                  = 'absent', +  $mod_security                     = true, +  $mod_security_relevantonly        = true, +  $mod_security_rules_to_disable    = [], +  $mod_security_additional_options  = 'absent', +  $ssl_mode                         = false, +  $vhost_mode                       = 'template', +  $template_partial                 = 'apache/vhosts/php_joomla/partial.erb', +  $vhost_source                     = 'absent', +  $vhost_destination                = 'absent', +  $htpasswd_file                    = 'absent', +  $htpasswd_path                    = 'absent', +  $manage_config                    = true, +  $config_webwriteable              = false, +  $manage_directories               = true +){ +  include ::apache::include::joomla + +  $documentroot = $path ? { +    'absent' => $::operatingsystem ? { +      openbsd => "/var/www/htdocs/${name}/www", +      default => "/var/www/vhosts/${name}/www" +    }, +    default => "${path}/www" +  } + +  if $mod_security_additional_options == 'absent' { +    $id_str = $::operatingsystem ? { +      'CentOS'  => $::operatingsystemmajrelease ? { +        5       => '', +        default => 'id:1199400,' +      }, +      default => '' +    } +    $real_mod_security_additional_options = " +    # http://optics.csufresno.edu/~kriehn/fedora/fedora_files/f9/howto/modsecurity.html +    # Exceptions for Joomla Root Directory +    <LocationMatch \"^/\"> +        SecRuleRemoveById 950013 +    </LocationMatch> + +    # Exceptions for Joomla Administration Panel +    SecRule REQUEST_FILENAME \"/administrator/index2.php\" \"${id_str}allow,phase:1,nolog,ctl:ruleEngine=Off\" + +    # Exceptions for Joomla Component Expose +    <LocationMatch \"^/components/com_expose/expose/manager/amfphp/gateway.php\"> +        SecRuleRemoveById 960010 +    </LocationMatch> +" +  } else { +    $real_mod_security_additional_options = $mod_security_additional_options +  } + +  $std_joomla_php_settings = { +    'allow_url_fopen'   => 'on', +    'allow_url_include' => 'off', +  } + +  # create vhost configuration file +  ::apache::vhost::php::webapp{ +    $name: +      ensure                          => $ensure, +      configuration                   => $configuration, +      domain                          => $domain, +      domainalias                     => $domainalias, +      server_admin                    => $server_admin, +      logmode                         => $logmode, +      path                            => $path, +      owner                           => $owner, +      group                           => $group, +      documentroot_owner              => $documentroot_owner, +      documentroot_group              => $documentroot_group, +      documentroot_mode               => $documentroot_mode, +      run_mode                        => $run_mode, +      run_uid                         => $run_uid, +      run_gid                         => $run_gid, +      allow_override                  => $allow_override, +      php_settings                    => merge($std_joomla_php_settings, +        $php_settings), +      php_options                     => $php_options, +      php_installation                => $php_installation, +      do_includes                     => $do_includes, +      options                         => $options, +      additional_options              => $additional_options, +      default_charset                 => $default_charset, +      mod_security                    => $mod_security, +      mod_security_relevantonly       => $mod_security_relevantonly, +      mod_security_rules_to_disable   => $mod_security_rules_to_disable, +      mod_security_additional_options => $real_mod_security_additional_options, +      ssl_mode                        => $ssl_mode, +      vhost_mode                      => $vhost_mode, +      template_partial                => $template_partial, +      vhost_source                    => $vhost_source, +      vhost_destination               => $vhost_destination, +      htpasswd_file                   => $htpasswd_file, +      htpasswd_path                   => $htpasswd_path, +      manage_directories              => $manage_directories, +      managed_directories             => [ "${documentroot}/administrator/backups", +                                            "${documentroot}/administrator/components", +                                            "${documentroot}/administrator/language", +                                            "${documentroot}/administrator/modules", +                                            "${documentroot}/administrator/templates", +                                            "${documentroot}/components", +                                            "${documentroot}/dmdocuments", +                                            "${documentroot}/images", +                                            "${documentroot}/language", +                                            "${documentroot}/media", +                                            "${documentroot}/modules", +                                            "${documentroot}/plugins", +                                            "${documentroot}/templates", +                                            "${documentroot}/cache", +                                            "${documentroot}/tmp", +                                            "${documentroot}/administrator/cache" ], +      manage_config                   => $manage_config, +      config_webwriteable             => $config_webwriteable, +      config_file                     => 'configuration.php', +  } + +} + diff --git a/puppet/modules/apache/manifests/vhost/php/mediawiki.pp b/puppet/modules/apache/manifests/vhost/php/mediawiki.pp new file mode 100644 index 00000000..25881ca1 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/mediawiki.pp @@ -0,0 +1,106 @@ +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +define apache::vhost::php::mediawiki( +  $ensure = present, +  $configuration = {}, +  $domain = 'absent', +  $domainalias = 'absent', +  $server_admin = 'absent', +  $logmode = 'default', +  $path = 'absent', +  $manage_docroot = true, +  $owner = root, +  $group = apache, +  $documentroot_owner = apache, +  $documentroot_group = 0, +  $documentroot_mode = 0640, +  $run_mode = 'normal', +  $run_uid = 'absent', +  $run_gid = 'absent', +  $allow_override = 'FileInfo Limit', +  $php_settings = {}, +  $php_options = {}, +  $options = 'absent', +  $additional_options = 'absent', +  $default_charset = 'absent', +  $mod_security = true, +  $mod_security_relevantonly = true, +  $mod_security_rules_to_disable = [], +  $mod_security_additional_options = 'absent', +  $ssl_mode = false, +  $vhost_mode = 'template', +  $template_partial = 'apache/vhosts/php_mediawiki/partial.erb', +  $vhost_source = 'absent', +  $vhost_destination = 'absent', +  $htpasswd_file = 'absent', +  $htpasswd_path = 'absent' +){ + +  $mediawiki_php_settings = { +    safe_mode => false, +  } + +  # create vhost configuration file +  ::apache::vhost::php::webapp{$name: +    ensure                          => $ensure, +    configuration                   => $configuration, +    domain                          => $domain, +    domainalias                     => $domainalias, +    server_admin                    => $server_admin, +    logmode                         => $logmode, +    path                            => $path, +    manage_docroot                  => $manage_docroot, +    owner                           => $owner, +    group                           => $group, +    documentroot_owner              => $documentroot_owner, +    documentroot_group              => $documentroot_group, +    documentroot_mode               => $documentroot_mode, +    run_mode                        => $run_mode, +    run_uid                         => $run_uid, +    run_gid                         => $run_gid, +    allow_override                  => $allow_override, +    php_settings                    => merge($mediawiki_php_settings,$php_settings), +    php_options                     => $php_options, +    options                         => $options, +    additional_options              => $additional_options, +    default_charset                 => $default_charset, +    mod_security                    => $mod_security, +    mod_security_relevantonly       => $mod_security_relevantonly, +    mod_security_rules_to_disable   => $mod_security_rules_to_disable, +    mod_security_additional_options => $mod_security_additional_options, +    ssl_mode                        => $ssl_mode, +    vhost_mode                      => $vhost_mode, +    template_partial                => $template_partial, +    vhost_source                    => $vhost_source, +    vhost_destination               => $vhost_destination, +    htpasswd_file                   => $htpasswd_file, +    htpasswd_path                   => $htpasswd_path, +    manage_directories              => false, +    manage_config                   => false, +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/php/safe_mode_bin.pp b/puppet/modules/apache/manifests/vhost/php/safe_mode_bin.pp new file mode 100644 index 00000000..1c82e199 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/safe_mode_bin.pp @@ -0,0 +1,17 @@ +# safe_mode binaries +define apache::vhost::php::safe_mode_bin( +  $ensure = 'present', +  $path +){ +  $substr=regsubst($name,'^.*\/','','G') +  $real_path = "${path}/${substr}" +  $target = $ensure ? { +    'present' => regsubst($name,'^.*@',''), +    default => absent, +  } +  file{$real_path: +    ensure => link, +    target => $target, +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/php/silverstripe.pp b/puppet/modules/apache/manifests/vhost/php/silverstripe.pp new file mode 100644 index 00000000..1f19eab4 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/silverstripe.pp @@ -0,0 +1,119 @@ +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +define apache::vhost::php::silverstripe( +  $ensure                           = present, +  $configuration                    = {}, +  $domain                           = 'absent', +  $domainalias                      = 'absent', +  $server_admin                     = 'absent', +  $logmode                          = 'default', +  $path                             = 'absent', +  $owner                            = root, +  $group                            = apache, +  $documentroot_owner               = apache, +  $documentroot_group               = 0, +  $documentroot_mode                = '0640', +  $run_mode                         = 'normal', +  $run_uid                          = 'absent', +  $run_gid                          = 'absent', +  $allow_override                   = 'None', +  $php_settings                     = {}, +  $php_options                      = {}, +  $do_includes                      = false, +  $options                          = 'absent', +  $additional_options               = 'absent', +  $default_charset                  = 'absent', +  $mod_security                     = true, +  $mod_security_relevantonly        = true, +  $mod_security_rules_to_disable    = [], +  $mod_security_additional_options  = 'absent', +  $ssl_mode                         = false, +  $vhost_mode                       = 'template', +  $template_partial                 = 'apache/vhosts/php_silverstripe/partial.erb', +  $vhost_source                     = 'absent', +  $vhost_destination                = 'absent', +  $htpasswd_file                    = 'absent', +  $htpasswd_path                    = 'absent', +  $manage_config                    = true, +  $config_webwriteable              = false, +  $manage_directories               = true, +){ + +  include ::apache::include::silverstripe + +  $documentroot = $path ? { +    'absent' => $::operatingsystem ? { +      openbsd => "/var/www/htdocs/${name}/www", +      default => "/var/www/vhosts/${name}/www" +    }, +    default => "${path}/www" +  } +  $modsec_rules = ['960010'] +  $real_mod_security_rules_to_disable = union($mod_security_rules_to_disable,$modsec_rules) + +  # create vhost configuration file +  ::apache::vhost::php::webapp{$name: +    ensure                          => $ensure, +    configuration                   => $configuration, +    domain                          => $domain, +    domainalias                     => $domainalias, +    server_admin                    => $server_admin, +    logmode                         => $logmode, +    path                            => $path, +    owner                           => $owner, +    group                           => $group, +    documentroot_owner              => $documentroot_owner, +    documentroot_group              => $documentroot_group, +    documentroot_mode               => $documentroot_mode, +    run_mode                        => $run_mode, +    run_uid                         => $run_uid, +    run_gid                         => $run_gid, +    allow_override                  => $allow_override, +    php_settings                    => $php_settings, +    php_options                     => $php_options, +    do_includes                     => $do_includes, +    options                         => $options, +    additional_options              => $additional_options, +    default_charset                 => $default_charset, +    mod_security                    => $mod_security, +    mod_security_relevantonly       => $mod_security_relevantonly, +    mod_security_rules_to_disable   => $mod_security_rules_to_disable, +    mod_security_additional_options => $mod_security_additional_options, +    ssl_mode                        => $ssl_mode, +    vhost_mode                      => $vhost_mode, +    template_partial                => $template_partial, +    vhost_source                    => $vhost_source, +    vhost_destination               => $vhost_destination, +    htpasswd_file                   => $htpasswd_file, +    htpasswd_path                   => $htpasswd_path, +    manage_directories              => $manage_directories, +    managed_directories             =>  [ "${documentroot}/assets" ], +    manage_config                   => $manage_config, +  } + +} + diff --git a/puppet/modules/apache/manifests/vhost/php/simplemachine.pp b/puppet/modules/apache/manifests/vhost/php/simplemachine.pp new file mode 100644 index 00000000..3fa11a77 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/simplemachine.pp @@ -0,0 +1,125 @@ +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +define apache::vhost::php::simplemachine( +  $ensure                           = present, +  $configuration                    = {}, +  $domain                           = 'absent', +  $domainalias                      = 'absent', +  $server_admin                     = 'absent', +  $logmode                          = 'default', +  $path                             = 'absent', +  $owner                            = root, +  $group                            = apache, +  $documentroot_owner               = apache, +  $documentroot_group               = 0, +  $documentroot_mode                = '0640', +  $run_mode                         = 'normal', +  $run_uid                          = 'absent', +  $run_gid                          = 'absent', +  $allow_override                   = 'None', +  $php_settings                     = {}, +  $php_options                      = {}, +  $do_includes                      = false, +  $options                          = 'absent', +  $additional_options               = 'absent', +  $default_charset                  = 'absent', +  $mod_security                     = true, +  $mod_security_relevantonly        = true, +  $mod_security_rules_to_disable    = [], +  $mod_security_additional_options  = 'absent', +  $ssl_mode                         = false, +  $vhost_mode                       = 'template', +  $template_partial                 = 'apache/vhosts/php/partial.erb', +  $vhost_source                     = 'absent', +  $vhost_destination                = 'absent', +  $htpasswd_file                    = 'absent', +  $htpasswd_path                    = 'absent', +  $manage_config                    = true, +  $config_webwriteable              = false, +  $manage_directories               = true, +){ +  $documentroot = $path ? { +    'absent' => $::operatingsystem ? { +      openbsd => "/var/www/htdocs/${name}/www", +      default => "/var/www/vhosts/${name}/www" +    }, +    default => "${path}/www" +  } + +  # create vhost configuration file +  ::apache::vhost::php::webapp{$name: +    ensure                          => $ensure, +    configuration                   => $configuration, +    domain                          => $domain, +    domainalias                     => $domainalias, +    server_admin                    => $server_admin, +    logmode                         => $logmode, +    path                            => $path, +    owner                           => $owner, +    group                           => $group, +    documentroot_owner              => $documentroot_owner, +    documentroot_group              => $documentroot_group, +    documentroot_mode               => $documentroot_mode, +    run_mode                        => $run_mode, +    run_uid                         => $run_uid, +    run_gid                         => $run_gid, +    allow_override                  => $allow_override, +    php_settings                    => $php_settings, +    php_options                     => $php_options, +    do_includes                     => $do_includes, +    options                         => $options, +    additional_options              => $additional_options, +    default_charset                 => $default_charset, +    mod_security                    => $mod_security, +    mod_security_relevantonly       => $mod_security_relevantonly, +    mod_security_rules_to_disable   => $mod_security_rules_to_disable, +    mod_security_additional_options => $mod_security_additional_options, +    ssl_mode                        => $ssl_mode, +    vhost_mode                      => $vhost_mode, +    template_partial                => $template_partial, +    vhost_source                    => $vhost_source, +    vhost_destination               => $vhost_destination, +    htpasswd_file                   => $htpasswd_file, +    htpasswd_path                   => $htpasswd_path, +    manage_directories              => $manage_directories, +    managed_directories             => [ +      "${documentroot}/agreement.txt", +      "${documentroot}/attachments", +      "${documentroot}/avatars", +      "${documentroot}/cache", +      "${documentroot}/Packages", +      "${documentroot}/Packages/installed.list", +      "${documentroot}/Smileys", +      "${documentroot}/Themes", +      "${documentroot}/Themes/default/languages/Install.english.php" +    ], +    manage_config                   => $manage_config, +    config_webwriteable             => $config_webwriteable, +    config_file                     => 'Settings.php', +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/php/spip.pp b/puppet/modules/apache/manifests/vhost/php/spip.pp new file mode 100644 index 00000000..e33c1dfe --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/spip.pp @@ -0,0 +1,114 @@ +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +define apache::vhost::php::spip( +  $ensure                           = present, +  $configuration                    = {}, +  $domain                           = 'absent', +  $domainalias                      = 'absent', +  $server_admin                     = 'absent', +  $logmode                          = 'default', +  $path                             = 'absent', +  $owner                            = root, +  $group                            = apache, +  $documentroot_owner               = apache, +  $documentroot_group               = 0, +  $documentroot_mode                = '0640', +  $run_mode                         = 'normal', +  $run_uid                          = 'absent', +  $run_gid                          = 'absent', +  $allow_override                   = 'FileInfo', +  $php_settings                     = {}, +  $php_options                      = {}, +  $template_partial                 = 'apache/vhosts/php/partial.erb', +  $do_includes                      = false, +  $options                          = 'absent', +  $additional_options               = 'absent', +  $default_charset                  = 'absent', +  $mod_security                     = true, +  $mod_security_relevantonly        = true, +  $mod_security_rules_to_disable    = [], +  $mod_security_additional_options  = 'absent', +  $ssl_mode                         = false, +  $vhost_mode                       = 'template', +  $vhost_source                     = 'absent', +  $vhost_destination                = 'absent', +  $htpasswd_file                    = 'absent', +  $htpasswd_path                    = 'absent' +){ +  $documentroot = $path ? { +    'absent' => $::operatingsystem ? { +      openbsd => "/var/www/htdocs/${name}/www", +      default => "/var/www/vhosts/${name}/www" +    }, +    default => "${path}/www" +  } + +  # create vhost configuration file +  ::apache::vhost::php::webapp{$name: +    ensure                          => $ensure, +    configuration                   => $configuration, +    domain                          => $domain, +    domainalias                     => $domainalias, +    server_admin                    => $server_admin, +    logmode                         => $logmode, +    path                            => $path, +    owner                           => $owner, +    group                           => $group, +    documentroot_owner              => $documentroot_owner, +    documentroot_group              => $documentroot_group, +    documentroot_mode               => $documentroot_mode, +    run_mode                        => $run_mode, +    run_uid                         => $run_uid, +    run_gid                         => $run_gid, +    allow_override                  => $allow_override, +    php_settings                    => $php_settings, +    php_options                     => $php_options, +    do_includes                     => $do_includes, +    options                         => $options, +    additional_options              => $additional_options, +    default_charset                 => $default_charset, +    mod_security                    => $mod_security, +    mod_security_relevantonly       => $mod_security_relevantonly, +    mod_security_rules_to_disable   => $mod_security_rules_to_disable, +    mod_security_additional_options => $mod_security_additional_options, +    ssl_mode                        => $ssl_mode, +    vhost_mode                      => $vhost_mode, +    template_partial                => $template_partial, +    vhost_source                    => $vhost_source, +    vhost_destination               => $vhost_destination, +    htpasswd_file                   => $htpasswd_file, +    htpasswd_path                   => $htpasswd_path, +    managed_directories             => [ +      "${documentroot}/IMG", +      "${documentroot}/tmp", +      "${documentroot}/local", +      "${documentroot}/config" +    ], +    manage_config                   => false, +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/php/standard.pp b/puppet/modules/apache/manifests/vhost/php/standard.pp new file mode 100644 index 00000000..3870707a --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/standard.pp @@ -0,0 +1,304 @@ +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +define apache::vhost::php::standard( +  $ensure                           = present, +  $configuration                    = {}, +  $domain                           = 'absent', +  $domainalias                      = 'absent', +  $server_admin                     = 'absent', +  $logmode                          = 'default', +  $logpath                          = 'absent', +  $logprefix                        = '', +  $path                             = 'absent', +  $manage_webdir                    = true, +  $path_is_webdir                   = false, +  $manage_docroot                   = true, +  $owner                            = root, +  $group                            = apache, +  $documentroot_owner               = apache, +  $documentroot_group               = 0, +  $documentroot_mode                = 0640, +  $run_mode                         = 'normal', +  $run_uid                          = 'absent', +  $run_gid                          = 'absent', +  $allow_override                   = 'None', +  $php_settings                     = {}, +  $php_options                      = {}, +  $php_installation                 = 'system', +  $do_includes                      = false, +  $options                          = 'absent', +  $additional_options               = 'absent', +  $default_charset                  = 'absent', +  $use_mod_macro                    = false, +  $mod_security                     = true, +  $mod_security_relevantonly        = true, +  $mod_security_rules_to_disable    = [], +  $mod_security_additional_options  = 'absent', +  $ssl_mode                         = false, +  $vhost_mode                       = 'template', +  $template_partial                 = 'apache/vhosts/php/partial.erb', +  $vhost_source                     = 'absent', +  $vhost_destination                = 'absent', +  $htpasswd_file                    = 'absent', +  $htpasswd_path                    = 'absent', +){ + +  if $manage_webdir { +    # create webdir +    ::apache::vhost::webdir{$name: +      ensure              => $ensure, +      path                => $path, +      owner               => $owner, +      group               => $group, +      run_mode            => $run_mode, +      manage_docroot      => $manage_docroot, +      documentroot_owner  => $documentroot_owner, +      documentroot_group  => $documentroot_group, +      documentroot_mode   => $documentroot_mode, +    } +  } + +  $real_path = $path ? { +    'absent' => $::operatingsystem ? { +      openbsd => "/var/www/htdocs/${name}", +      default => "/var/www/vhosts/${name}" +    }, +    default   => $path +  } + +  if $path_is_webdir { +    $documentroot = $real_path +  } else { +    $documentroot = "${real_path}/www" +  } +  $logdir = $logpath ? { +    'absent'  => "${real_path}/logs", +    default   => $logpath +  } + +  $std_php_options = { +    smarty  => false, +    pear    => false, +  } +  $real_php_options = merge($std_php_options,$php_options) + +  if $real_php_options[smarty] { +    include php::extensions::smarty +    $smarty_path = '/usr/share/php/Smarty/:' +  } else { +    $smarty_path = '' +  } + +  if $real_php_options[pear] { +    $pear_path = '/usr/share/pear/:' +  } else { +    $pear_path = '' +  } + +  if $logmode != 'nologs' { +    $php_error_log = "${logdir}/php_error_log" +  } else { +    $php_error_log = undef +  } + +  if ('safe_mode_exec_dir' in $php_settings) { +    $php_safe_mode_exec_dir = $php_settings[safe_mode_exec_dir] +  } else { +    $php_safe_mode_exec_dir =  $path ? { +      'absent' => $::operatingsystem ? { +        openbsd => "/var/www/htdocs/${name}/bin", +        default => "/var/www/vhosts/${name}/bin" +      }, +      default   => "${path}/bin" +    } +  } +  file{$php_safe_mode_exec_dir: +    recurse => true, +    force   => true, +    purge   => true, +  } +  if ('safe_mode_exec_bins' in $php_options) { +    $std_php_settings_safe_mode_exec_dir = $php_safe_mode_exec_dir +    $ensure_exec = $ensure ? { +      'present'  => directory, +      default    => 'absent', +    } +    File[$php_safe_mode_exec_dir]{ +      ensure => $ensure_exec, +      owner  => $documentroot_owner, +      group  => $documentroot_group, +      mode   => '0750', +    } +    $php_safe_mode_exec_bins_subst = regsubst($php_options[safe_mode_exec_bins],'(.+)',"${name}@\\1") +    apache::vhost::php::safe_mode_bin{ +      $php_safe_mode_exec_bins_subst: +        ensure  => $ensure, +        path    => $php_safe_mode_exec_dir; +    } +  } else { +    $std_php_settings_safe_mode_exec_dir = undef +    File[$php_safe_mode_exec_dir]{ +      ensure => absent, +    } +  } + +  if !('default_charset' in $php_settings) and ($default_charset != 'absent') { +    $std_php_settings_default_charset =  $default_charset ? { +      'On'    => 'iso-8859-1', +      default => $default_charset +    } +  } else { +    $std_php_settings_default_charset = undef +  } + +  if ('additional_open_basedir' in $php_options) { +    $the_open_basedir = "${smarty_path}${pear_path}${documentroot}:${real_path}/data:/var/www/upload_tmp_dir/${name}:/var/www/session.save_path/${name}:${php_options[additional_open_basedir]}" +  } else { +    $the_open_basedir = "${smarty_path}${pear_path}${documentroot}:${real_path}/data:/var/www/upload_tmp_dir/${name}:/var/www/session.save_path/${name}" +  } + +  if $run_mode == 'fcgid' { +    $safe_mode_gid = $::operatingsystem ? { +      debian  => undef, +      default => $php_installation ? { +        'system'  => 'On', +        default   => undef, +      } +    } +  } else { +    $safe_mode_gid = undef +  } + +  $safe_mode = $::operatingsystem ? { +    debian  => undef, +    default => $php_installation ? { +      'system'  => 'On', +      default   => undef, +    } +  } +  $std_php_settings = { +    engine              => 'On', +    upload_tmp_dir      => "/var/www/upload_tmp_dir/${name}", +    'session.save_path' => "/var/www/session.save_path/${name}", +    error_log           => $php_error_log, +    safe_mode           => $safe_mode, +    safe_mode_gid       => $safe_mode_gid, +    safe_mode_exec_dir  => $std_php_settings_safe_mode_exec_dir, +    default_charset     => $std_php_settings_default_charset, +    open_basedir        => $the_open_basedir, +  } + +  $real_php_settings = merge($std_php_settings,$php_settings) + +  if $ensure != 'absent' { +    case $run_mode { +      'proxy-itk','static-itk': { +        include ::php::itk_plus +      } +      'itk': { include ::php::itk } +      'fcgid': { +        include ::mod_fcgid +        include ::php::mod_fcgid +        include apache::include::mod_fcgid + +        mod_fcgid::starter {$name: +          tmp_dir          => $real_php_settings[php_tmp_dir], +          cgi_type         => 'php', +          cgi_type_options => delete($real_php_settings, php_tmp_dir), +          owner            => $run_uid, +          group            => $run_gid, +          notify           => Service['apache'], +        } +        if $php_installation == 'scl54' { +          require php::scl::php54 +          Mod_fcgid::Starter[$name]{ +            binary          => '/opt/rh/php54/root/usr/bin/php-cgi', +            additional_cmds => 'source /opt/rh/php54/enable', +            rc              => '/opt/rh/php54/root/etc', +          } +        } elsif $php_installation == 'scl55' { +          require php::scl::php55 +          Mod_fcgid::Starter[$name]{ +            binary          => '/opt/rh/php55/root/usr/bin/php-cgi', +            additional_cmds => 'source /opt/rh/php55/enable', +            rc              => '/opt/rh/php55/root/etc', +          } +        } +      } +      default: { include ::php } +    } +  } + +  ::apache::vhost::phpdirs{$name: +    ensure                => $ensure, +    php_upload_tmp_dir    => $real_php_settings[upload_tmp_dir], +    php_session_save_path => $real_php_settings['session.save_path'], +    documentroot_owner    => $documentroot_owner, +    documentroot_group    => $documentroot_group, +    documentroot_mode     => $documentroot_mode, +    run_mode              => $run_mode, +    run_uid               => $run_uid, +  } + +  # create vhost configuration file +  ::apache::vhost{$name: +    ensure                          => $ensure, +    configuration                   => $configuration, +    path                            => $path, +    path_is_webdir                  => $path_is_webdir, +    vhost_mode                      => $vhost_mode, +    template_partial                => $template_partial, +    vhost_source                    => $vhost_source, +    vhost_destination               => $vhost_destination, +    domain                          => $domain, +    domainalias                     => $domainalias, +    server_admin                    => $server_admin, +    logmode                         => $logmode, +    logpath                         => $logpath, +    logprefix                       => $logprefix, +    run_mode                        => $run_mode, +    run_uid                         => $run_uid, +    run_gid                         => $run_gid, +    allow_override                  => $allow_override, +    do_includes                     => $do_includes, +    options                         => $options, +    additional_options              => $additional_options, +    default_charset                 => $default_charset, +    php_settings                    => $real_php_settings, +    php_options                     => $real_php_options, +    ssl_mode                        => $ssl_mode, +    htpasswd_file                   => $htpasswd_file, +    htpasswd_path                   => $htpasswd_path, +    mod_security                    => $mod_security, +    mod_security_relevantonly       => $mod_security_relevantonly, +    mod_security_rules_to_disable   => $mod_security_rules_to_disable, +    mod_security_additional_options => $mod_security_additional_options, +    use_mod_macro                   => $use_mod_macro, +    passing_extension               => 'php', +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/php/typo3.pp b/puppet/modules/apache/manifests/vhost/php/typo3.pp new file mode 100644 index 00000000..d9e877a6 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/typo3.pp @@ -0,0 +1,150 @@ +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +define apache::vhost::php::typo3( +  $ensure                           = present, +  $configuration                    = {}, +  $domain                           = 'absent', +  $domainalias                      = 'absent', +  $server_admin                     = 'absent', +  $logmode                          = 'default', +  $path                             = 'absent', +  $owner                            = root, +  $group                            = apache, +  $documentroot_owner               = apache, +  $documentroot_group               = 0, +  $documentroot_mode                = '0640', +  $run_mode                         = 'normal', +  $run_uid                          = 'absent', +  $run_gid                          = 'absent', +  $allow_override                   = 'None', +  $php_settings                     = {}, +  $php_options                      = {}, +  $do_includes                      = false, +  $options                          = 'absent', +  $additional_options               = 'absent', +  $default_charset                  = 'absent', +  $mod_security                     = true, +  $mod_security_relevantonly        = true, +  $mod_security_rules_to_disable    = [], +  $mod_security_additional_options  = 'absent', +  $ssl_mode                         = false, +  $vhost_mode                       = 'template', +  $template_partial                 = 'apache/vhosts/php_typo3/partial.erb', +  $vhost_source                     = 'absent', +  $vhost_destination                = 'absent', +  $htpasswd_file                    = 'absent', +  $htpasswd_path                    = 'absent', +  $manage_config                    = true, +  $config_webwriteable              = false, +  $manage_directories               = true, +){ +  $documentroot = $path ? { +    'absent' => $::operatingsystem ? { +        openbsd => "/var/www/htdocs/${name}/www", +        default => "/var/www/vhosts/${name}/www" +    }, +    default => "${path}/www" +  } + +  $modsec_rules = ['960010'] +  $real_mod_security_rules_to_disable = union($mod_security_rules_to_disable,$modsec_rules) +  if $mod_security_additional_options == 'absent' { +  $real_mod_security_additional_options = ' +    <Location "/typo3"> +      SecRuleEngine Off +      SecAuditEngine Off +    </Location> +' +  } else { +    $real_mod_security_additional_options = $mod_security_additional_options +  } + +  $typo3_php_settings = { +    # turn allow_url_fopen on for the extension manager fetch +    allow_url_fopen => 'On' +  } +  $real_php_settings = merge($typo3_php_settings,$php_settings) + +  # create vhost configuration file +  ::apache::vhost::php::webapp{$name: +    ensure                          => $ensure, +    configuration                   => $configuration, +    domain                          => $domain, +    domainalias                     => $domainalias, +    server_admin                    => $server_admin, +    logmode                         => $logmode, +    path                            => $path, +    owner                           => $owner, +    group                           => $group, +    documentroot_owner              => $documentroot_owner, +    documentroot_group              => $documentroot_group, +    documentroot_mode               => $documentroot_mode, +    run_mode                        => $run_mode, +    run_uid                         => $run_uid, +    run_gid                         => $run_gid, +    allow_override                  => $allow_override, +    php_settings                    => $real_php_settings, +    php_options                     => $php_options, +    do_includes                     => $do_includes, +    options                         => $options, +    additional_options              => $additional_options, +    default_charset                 => $default_charset, +    mod_security                    => $mod_security, +    mod_security_relevantonly       => $mod_security_relevantonly, +    mod_security_rules_to_disable   => $real_mod_security_rules_to_disable, +    mod_security_additional_options => $real_mod_security_additional_options, +    ssl_mode                        => $ssl_mode, +    vhost_mode                      => $vhost_mode, +    template_partial                => $template_partial, +    vhost_source                    => $vhost_source, +    vhost_destination               => $vhost_destination, +    htpasswd_file                   => $htpasswd_file, +    htpasswd_path                   => $htpasswd_path, +    manage_directories              => $manage_directories, +    managed_directories             =>  [ "${documentroot}/typo3temp", +                                          "${documentroot}/typo3temp/pics", +                                          "${documentroot}/typo3temp/temp", +                                          "${documentroot}/typo3temp/llxml", +                                          "${documentroot}/typo3temp/cs", +                                          "${documentroot}/typo3temp/GB", +                                          "${documentroot}/typo3temp/locks", +                                          "${documentroot}/typo3conf", +                                          "${documentroot}/typo3conf/ext", +                                          "${documentroot}/typo3conf/l10n", +                                          # "${documentroot}/typo3/ext/", # only needed for ext manager installing global extensions +                                          "${documentroot}/uploads", +                                          "${documentroot}/uploads/pics", +                                          "${documentroot}/uploads/media", +                                          "${documentroot}/uploads/tf", +                                          "${documentroot}/fileadmin", +                                          "${documentroot}/fileadmin/_temp_" +                                        ], +    manage_config                   => $manage_config, +  } + +} + diff --git a/puppet/modules/apache/manifests/vhost/php/webapp.pp b/puppet/modules/apache/manifests/vhost/php/webapp.pp new file mode 100644 index 00000000..695120d0 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/webapp.pp @@ -0,0 +1,148 @@ +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +define apache::vhost::php::webapp( +  $ensure                           = present, +  $configuration                    = {}, +  $domain                           = 'absent', +  $domainalias                      = 'absent', +  $server_admin                     = 'absent', +  $logmode                          = 'default', +  $path                             = 'absent', +  $manage_webdir                    = true, +  $manage_docroot                   = true, +  $owner                            = root, +  $group                            = apache, +  $documentroot_owner               = apache, +  $documentroot_group               = 0, +  $documentroot_mode                = '0640', +  $run_mode                         = 'normal', +  $run_uid                          = 'absent', +  $run_gid                          = 'absent', +  $allow_override                   = 'None', +  $php_settings                     = {}, +  $php_options                      = {}, +  $php_installation                 = 'system', +  $do_includes                      = false, +  $options                          = 'absent', +  $additional_options               = 'absent', +  $default_charset                  = 'absent', +  $mod_security                     = true, +  $mod_security_relevantonly        = true, +  $mod_security_rules_to_disable    = [], +  $mod_security_additional_options  = 'absent', +  $ssl_mode                         = false, +  $vhost_mode                       = 'template', +  $template_partial, +  $vhost_source                     = 'absent', +  $vhost_destination                = 'absent', +  $htpasswd_file                    = 'absent', +  $htpasswd_path                    = 'absent', +  $manage_config                    = true, +  $config_file                      = 'absent', +  $config_webwriteable              = false, +  $manage_directories               = true, +  $managed_directories              = 'absent', +){ +  if ($ensure != 'absent') { +    if $manage_directories and ($managed_directories != 'absent') { +      ::apache::file::rw{ $managed_directories : +        owner => $documentroot_owner, +        group => $documentroot_group, +      } +    } + +    if $manage_config { +      if $config_file == 'absent' { fail("No config file defined for ${name} on ${::fqdn}, if you'd like to manage the config, you have to add one!") } + +      $real_path = $path ? { +        'absent' => $::operatingsystem ? { +          openbsd => "/var/www/htdocs/${name}", +          default => "/var/www/vhosts/${name}" +        }, +        default => $path +      } +      $documentroot = "${real_path}/www" +      ::apache::vhost::file::documentrootfile{"configurationfile_${name}": +        documentroot  => $documentroot, +        filename      => $config_file, +        thedomain     => $name, +        owner         => $documentroot_owner, +        group         => $documentroot_group, +      } +      if $config_webwriteable { +        Apache::Vhost::File::Documentrootfile["configurationfile_${name}"]{ +          mode => '0660', +        } +      } else { +        Apache::Vhost::File::Documentrootfile["configurationfile_${name}"]{ +          mode => '0440', +        } +      } +    } +  } + +  # create vhost configuration file +  ::apache::vhost::php::standard{$name: +    ensure                          => $ensure, +    configuration                   => $configuration, +    domain                          => $domain, +    domainalias                     => $domainalias, +    server_admin                    => $server_admin, +    logmode                         => $logmode, +    path                            => $path, +    manage_webdir                   => $manage_webdir, +    manage_docroot                  => $manage_docroot, +    owner                           => $owner, +    group                           => $group, +    documentroot_owner              => $documentroot_owner, +    documentroot_group              => $documentroot_group, +    documentroot_mode               => $documentroot_mode, +    run_mode                        => $run_mode, +    run_uid                         => $run_uid, +    run_gid                         => $run_gid, +    allow_override                  => $allow_override, +    php_settings                    => $php_settings, +    php_options                     => $php_options, +    php_installation                => $php_installation, +    do_includes                     => $do_includes, +    options                         => $options, +    additional_options              => $additional_options, +    default_charset                 => $default_charset, +    mod_security                    => $mod_security, +    mod_security_relevantonly       => $mod_security_relevantonly, +    mod_security_rules_to_disable   => $mod_security_rules_to_disable, +    mod_security_additional_options => $mod_security_additional_options, +    ssl_mode                        => $ssl_mode, +    vhost_mode                      => $vhost_mode, +    template_partial                => $template_partial, +    vhost_source                    => $vhost_source, +    vhost_destination               => $vhost_destination, +    htpasswd_file                   => $htpasswd_file, +    htpasswd_path                   => $htpasswd_path, +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/php/wordpress.pp b/puppet/modules/apache/manifests/vhost/php/wordpress.pp new file mode 100644 index 00000000..a6bbe434 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/php/wordpress.pp @@ -0,0 +1,123 @@ +# run_mode: controls in which mode the vhost should be run, there are different +#           setups #           possible: +#   - normal: (*default*) run vhost with the current active worker +#             (default: prefork) don't setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in +#          combination with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just +#                proxies all the requests for the itk setup, that listens only +#                on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk +#                 setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves +#                 all the static content and proxies the dynamic calls to the +#                 itk setup, that listens only on the loobpack device +#                 (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security +#               module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +define apache::vhost::php::wordpress( +  $ensure                           = present, +  $configuration                    = {}, +  $domain                           = 'absent', +  $domainalias                      = 'absent', +  $server_admin                     = 'absent', +  $logmode                          = 'default', +  $path                             = 'absent', +  $owner                            = root, +  $group                            = apache, +  $documentroot_owner               = apache, +  $documentroot_group               = 0, +  $documentroot_mode                = '0640', +  $run_mode                         = 'normal', +  $run_uid                          = 'absent', +  $run_gid                          = 'absent', +  $allow_override                   = 'FileInfo Indexes', +  $php_settings                     = {}, +  $php_options                      = {}, +  $do_includes                      = false, +  $options                          = 'absent', +  $additional_options               = 'absent', +  $default_charset                  = 'absent', +  $mod_security                     = true, +  $mod_security_relevantonly        = true, +  $mod_security_rules_to_disable    = [], +  $mod_security_additional_options  = 'absent', +  $ssl_mode                         = false, +  $vhost_mode                       = 'template', +  $template_partial                 = 'apache/vhosts/php_wordpress/partial.erb', +  $vhost_source                     = 'absent', +  $vhost_destination                = 'absent', +  $htpasswd_file                    = 'absent', +  $htpasswd_path                    = 'absent', +  $manage_config                    = true, +  $config_webwriteable              = false, +  $manage_directories               = true +){ + +  $documentroot = $path ? { +    'absent' => $::operatingsystem ? { +        'openbsd' => "/var/www/htdocs/${name}/www", +        default   => "/var/www/vhosts/${name}/www" +    }, +    default => "${path}/www" +  } +  $modsec_rules = ['960010', '950018'] +  $real_mod_security_rules_to_disable = union($mod_security_rules_to_disable, +                                                $modsec_rules) + +  # create vhost configuration file +  apache::vhost::php::webapp{$name: +    ensure                          => $ensure, +    configuration                   => $configuration, +    domain                          => $domain, +    domainalias                     => $domainalias, +    server_admin                    => $server_admin, +    logmode                         => $logmode, +    path                            => $path, +    owner                           => $owner, +    group                           => $group, +    documentroot_owner              => $documentroot_owner, +    documentroot_group              => $documentroot_group, +    documentroot_mode               => $documentroot_mode, +    run_mode                        => $run_mode, +    run_uid                         => $run_uid, +    run_gid                         => $run_gid, +    allow_override                  => $allow_override, +    php_settings                    => $php_settings, +    php_options                     => $php_options, +    do_includes                     => $do_includes, +    options                         => $options, +    additional_options              => $additional_options, +    default_charset                 => $default_charset, +    mod_security                    => $mod_security, +    mod_security_relevantonly       => $mod_security_relevantonly, +    mod_security_rules_to_disable   => $real_mod_security_rules_to_disable, +    mod_security_additional_options => $mod_security_additional_options, +    ssl_mode                        => $ssl_mode, +    vhost_mode                      => $vhost_mode, +    template_partial                => $template_partial, +    vhost_source                    => $vhost_source, +    vhost_destination               => $vhost_destination, +    htpasswd_file                   => $htpasswd_file, +    htpasswd_path                   => $htpasswd_path, +    manage_directories              => $manage_directories, +    managed_directories             => [ "${documentroot}/wp-content/uploads",], +    manage_config                   => $manage_config, +    config_webwriteable             => $config_webwriteable, +    config_file                     => 'wp-config.php', +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/phpdirs.pp b/puppet/modules/apache/manifests/vhost/phpdirs.pp new file mode 100644 index 00000000..5936da61 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/phpdirs.pp @@ -0,0 +1,39 @@ +define apache::vhost::phpdirs( +  $ensure = present, +  $php_upload_tmp_dir, +  $php_session_save_path, +  $documentroot_owner = apache, +  $documentroot_group = 0, +  $documentroot_mode = 0750, +  $run_mode = 'normal', +  $run_uid = 'absent' +){ +  case $ensure { +    absent : { +      file { +        [$php_upload_tmp_dir, $php_session_save_path] : +          ensure => absent, +          purge => true, +          force => true, +          recurse => true, +      } +    } +    default : { +      include apache::defaultphpdirs +      file { +        [$php_upload_tmp_dir, $php_session_save_path] : +          ensure => directory, +          owner => $run_mode ? { +            'itk' => $run_uid, +            'static-itk' => $run_uid, +            'proxy-itk' => $run_uid, +            'fcgid' => $run_uid, +            default => $documentroot_owner +          }, +          group => $documentroot_group, +          mode => $documentroot_mode ; +      } +    } +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/proxy.pp b/puppet/modules/apache/manifests/vhost/proxy.pp new file mode 100644 index 00000000..95ae2059 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/proxy.pp @@ -0,0 +1,67 @@ +# Proxy VHost +# Parameters: +# +# - ensure: wether this vhost is `present` or `absent` +# - domain: the domain to redirect (*name*) +# - domainalias: A list of whitespace seperated domains to redirect +# - target_url: the url to be proxied. Note: We don't want http://example.com/foobar only example.com/foobar +# - server_admin: the email that is shown as responsible +# - ssl_mode: wether this vhost supports ssl or not +#   - false: don't enable ssl for this vhost (default) +#   - true: enable ssl for this vhost +#   - force: enable ssl and redirect non-ssl to ssl +#   - only: enable ssl only +# +# logmode: +# +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +# +define apache::vhost::proxy( +    $ensure = present, +    $configuration = {}, +    $domain = 'absent', +    $domainalias = 'absent', +    $htpasswd_file = 'absent', +    $target_url, +    $server_admin = 'absent', +    $logmode = 'default', +    $mod_security = false, +    $ssl_mode = false, +    $mod_security_relevantonly = true, +    $mod_security_rules_to_disable = [], +    $mod_security_additional_options = 'absent', +    $additional_options = 'absent' +){ +    # create vhost configuration file +    # we use the options field as the target_url +    ::apache::vhost::template{$name: +        ensure => $ensure, +        configuration => $configuration, +        template_partial => 'apache/vhosts/proxy/partial.erb', +        domain => $domain, +        path => 'really_absent', +        path_is_webdir => true, +        htpasswd_file => $htpasswd_file, +        domainalias => $domainalias, +        server_admin => $server_admin, +        logpath => $::operatingsystem ? { +          openbsd => '/var/www/logs', +          centos => '/var/log/httpd', +          default => '/var/log/apache2' +        }, +        logmode => $logmode, +        allow_override => $allow_override, +        run_mode => 'normal', +        mod_security => $mod_security, +        mod_security_relevantonly => $mod_security_relevantonly, +        mod_security_rules_to_disable => $mod_security_rules_to_disable, +        mod_security_additional_options => $mod_security_additional_options, +        options => $target_url, +        ssl_mode => $ssl_mode, +        additional_options => $additional_options, +    } +} + diff --git a/puppet/modules/apache/manifests/vhost/redirect.pp b/puppet/modules/apache/manifests/vhost/redirect.pp new file mode 100644 index 00000000..0ac40cc3 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/redirect.pp @@ -0,0 +1,56 @@ +# Redirect VHost to redirect hosts +# Parameters: +# +# - ensure: wether this vhost is `present` or `absent` +# - domain: the domain to redirect (*name*) +# - domainalias: A list of whitespace seperated domains to redirect +# - target_url: the url to redirect to. Note: We don't want http://example.com/foobar only example.com/foobar +# - server_admin: the email that is shown as responsible +# - ssl_mode: wether this vhost supports ssl or not +#   - false: don't enable ssl for this vhost (default) +#   - true: enable ssl for this vhost +#   - force: enable ssl and redirect non-ssl to ssl +#   - only: enable ssl only +# +# logmode: +# +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +# +define apache::vhost::redirect( +    $ensure = present, +    $configuration = {}, +    $domain = 'absent', +    $domainalias = 'absent', +    $target_url, +    $server_admin = 'absent', +    $logmode = 'default', +    $ssl_mode = false +){ +    # create vhost configuration file +    # we use the options field as the target_url +    ::apache::vhost::template{$name: +        ensure => $ensure, +        configuration => $configuration, +        template_partial => 'apache/vhosts/redirect/partial.erb', +        domain => $domain, +        path => 'really_absent', +        path_is_webdir => true, +        domainalias => $domainalias, +        server_admin => $server_admin, +        logpath => $::operatingsystem ? { +          openbsd => '/var/www/logs', +          centos => '/var/log/httpd', +          default => '/var/log/apache2' +        }, +        logmode => $logmode, +        allow_override => $allow_override, +        run_mode => 'normal', +        mod_security => false, +        options => $target_url, +        ssl_mode => $ssl_mode, +    } +} + diff --git a/puppet/modules/apache/manifests/vhost/static.pp b/puppet/modules/apache/manifests/vhost/static.pp new file mode 100644 index 00000000..f9197662 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/static.pp @@ -0,0 +1,86 @@ +# vhost_mode: which option is chosen to deploy the vhost +#   - template: generate it from a template (default) +#   - file: deploy a vhost file (apache::vhost::file will be called directly) +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: (*default*) don't activate mod_security +#    - true: activate mod_security +# +define apache::vhost::static( +    $ensure                           = present, +    $configuration                    = {}, +    $domain                           = 'absent', +    $domainalias                      = 'absent', +    $server_admin                     = 'absent', +    $logmode                          = 'default', +    $path                             = 'absent', +    $owner                            = root, +    $group                            = apache, +    $documentroot_owner               = apache, +    $documentroot_group               = 0, +    $documentroot_mode                = 0640, +    $allow_override                   = 'None', +    $do_includes                      = false, +    $options                          = 'absent', +    $additional_options               = 'absent', +    $default_charset                  = 'absent', +    $ssl_mode                         = false, +    $run_mode                         = 'normal', +    $vhost_mode                       = 'template', +    $template_partial                 = 'apache/vhosts/static/partial.erb', +    $vhost_source                     = 'absent', +    $vhost_destination                = 'absent', +    $htpasswd_file                    = 'absent', +    $htpasswd_path                    = 'absent', +    $mod_security                     = false, +    $mod_security_relevantonly        = true, +    $mod_security_rules_to_disable    = [], +    $mod_security_additional_options  = 'absent' +){ +    # create webdir +    ::apache::vhost::webdir{$name: +        ensure              => $ensure, +        path                => $path, +        owner               => $owner, +        group               => $group, +        run_mode            => $run_mode, +        datadir             => false, +        documentroot_owner  => $documentroot_owner, +        documentroot_group  => $documentroot_group, +        documentroot_mode   => $documentroot_mode, +    } + +    # create vhost configuration file +    ::apache::vhost{$name: +        ensure                          => $ensure, +        configuration                   => $configuration, +        path                            => $path, +        template_partial                => $template_partial, +        vhost_mode                      => $vhost_mode, +        vhost_source                    => $vhost_source, +        vhost_destination               => $vhost_destination, +        domain                          => $domain, +        domainalias                     => $domainalias, +        server_admin                    => $server_admin, +        logmode                         => $logmode, +        allow_override                  => $allow_override, +        do_includes                     => $do_includes, +        options                         => $options, +        additional_options              => $additional_options, +        default_charset                 => $default_charset, +        ssl_mode                        => $ssl_mode, +        htpasswd_file                   => $htpasswd_file, +        htpasswd_path                   => $htpasswd_path, +        mod_security                    => $mod_security, +        mod_security_relevantonly       => $mod_security_relevantonly, +        mod_security_rules_to_disable   => $mod_security_rules_to_disable, +        mod_security_additional_options => $mod_security_additional_options, +    } +} + diff --git a/puppet/modules/apache/manifests/vhost/template.pp b/puppet/modules/apache/manifests/vhost/template.pp new file mode 100644 index 00000000..8e9b798c --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/template.pp @@ -0,0 +1,158 @@ +# template_partial: +#  which template should be used to generate the type specific part +#  of the vhost entry. +# +# domainalias: +#   - absent: no domainalias is set (*default*) +#   - www: domainalias is set to www.$domain +#   - else: domainalias is set to that +# +# ssl_mode: wether this vhost supports ssl or not +#   - false: don't enable ssl for this vhost (default) +#   - true: enable ssl for this vhost +#   - force: enable ssl and redirect non-ssl to ssl +#   - only: enable ssl only +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +# +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: run vhost with a dual prefork/itk setup, where prefork serves all the static +#                 content and proxies the dynamic calls to the itk setup, that listens only on +#                 the loobpack device (Incompatibility: cannot be used in combination with +#                 'itk' mode) +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: don't activate mod_security +#    - true: (*default*) activate mod_security +# +define apache::vhost::template( +    $ensure                           = present, +    $configuration                    = {}, +    $path                             = 'absent', +    $path_is_webdir                   = false, +    $logpath                          = 'absent', +    $logmode                          = 'default', +    $logprefix                        = '', +    $domain                           = 'absent', +    $domainalias                      = 'absent', +    $server_admin                     = 'absent', +    $allow_override                   = 'None', +    $dav_db_dir                       = 'absent', +    $cgi_binpath                      = 'absent', +    $do_includes                      = false, +    $options                          = 'absent', +    $additional_options               = 'absent', +    $default_charset                  = 'absent', +    $php_options                      = {}, +    $php_settings                     = {}, +    $run_mode                         = 'normal', +    $run_uid                          = 'absent', +    $run_gid                          = 'absent', +    $template_partial                 = 'apache/vhosts/static/partial.erb', +    $template_vars                    = {}, +    $ssl_mode                         = false, +    $mod_security                     = true, +    $mod_security_relevantonly        = true, +    $mod_security_rules_to_disable    = [], +    $mod_security_additional_options  = 'absent', +    $use_mod_macro                    = false, +    $htpasswd_file                    = 'absent', +    $htpasswd_path                    = 'absent', +    $ldap_auth                        = false, +    $ldap_user                        = 'any', +    $passing_extension                = 'absent', +    $gempath                          = 'absent' +){ +    $real_path = $path ? { +        'absent'  => $::operatingsystem ? { +            openbsd => "/var/www/htdocs/${name}", +            default => "/var/www/vhosts/${name}" +        }, +        default   => $path +    } + +    if $path_is_webdir { +        $documentroot = $real_path +    } else { +        $documentroot = "${real_path}/www" +    } +    $logdir = $logpath ? { +        'absent'  => "${real_path}/logs", +        default   => $logpath +    } + +    $servername = $domain ? { +        'absent'  => $name, +        default   => $domain +    } +    $serveralias = $domainalias ? { +        'absent'  => '', +        'www'     => "www.${servername}", +        default   => $domainalias +    } +    if $htpasswd_path == 'absent' { +      $real_htpasswd_path = "/var/www/htpasswds/${name}" +    } else { +      $real_htpasswd_path = $htpasswd_path +    } +    case $run_mode { +      'proxy-itk': { $logfileprefix = 'proxy' } +      'static-itk': { $logfileprefix = 'static' } +    } +    case $run_mode { +        'fcgid','itk','proxy-itk','static-itk': { +            case $run_uid { +                'absent': { fail("you have to define run_uid for ${name} on ${::fqdn}") } +            } +            case $run_gid { +                'absent': { fail("you have to define run_gid for ${name} on ${::fqdn}") } +            } +        } +    } + +    # dav db dir +    case $dav_db_dir { +        'absent': { +            $real_dav_db_dir = "/var/www/dav_db_dir/${name}" +        } +        default: { $real_dav_db_dir = $dav_db_dir } +    } + +    apache::vhost::file{$name: +        configuration => $configuration, +        ensure        => $ensure, +        do_includes   => $do_includes, +        run_mode      => $run_mode, +        ssl_mode      => $ssl_mode, +        logmode       => $logmode, +        mod_security  => $mod_security, +        htpasswd_file => $htpasswd_file, +        htpasswd_path => $htpasswd_path, +        use_mod_macro => $use_mod_macro, +    } +    if $ensure != 'absent' { +      Apache::Vhost::File[$name]{ +        content => $run_mode ? { +          'proxy-itk'  => template('apache/vhosts/itk_plus.erb'), +          'static-itk' => template('apache/vhosts/itk_plus.erb'), +          default      => template('apache/vhosts/default.erb'), +        } +      } +    } +} + diff --git a/puppet/modules/apache/manifests/vhost/webdav.pp b/puppet/modules/apache/manifests/vhost/webdav.pp new file mode 100644 index 00000000..ff9e8abc --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/webdav.pp @@ -0,0 +1,126 @@ +# Webdav vhost: to manage webdav accessible targets +# run_mode: controls in which mode the vhost should be run, there are different setups +#           possible: +#   - normal: (*default*) run vhost with the current active worker (default: prefork) don't +#             setup anything special +#   - itk: run vhost with the mpm_itk module (Incompatibility: cannot be used in combination +#          with 'proxy-itk' & 'static-itk' mode) +#   - proxy-itk: run vhost with a dual prefork/itk setup, where prefork just proxies all the +#                requests for the itk setup, that listens only on the loobpack device. +#                (Incompatibility: cannot be used in combination with the itk setup.) +#   - static-itk: this mode is not possible and will be rewritten to proxy-itk +# +# run_uid: the uid the vhost should run as with the itk module +# run_gid: the gid the vhost should run as with the itk module +# +# mod_security: Whether we use mod_security or not (will include mod_security module) +#    - false: (*default*) don't activate mod_security +#    - true: activate mod_security +# +# logmode: +#   - default: Do normal logging to CustomLog and ErrorLog +#   - nologs: Send every logging to /dev/null +#   - anonym: Don't log ips for CustomLog, send ErrorLog to /dev/null +#   - semianonym: Don't log ips for CustomLog, log normal ErrorLog +# +define apache::vhost::webdav( +    $ensure                           = present, +    $configuration                    = {}, +    $domain                           = 'absent', +    $domainalias                      = 'absent', +    $server_admin                     = 'absent', +    $path                             = 'absent', +    $owner                            = root, +    $group                            = apache, +    $manage_webdir                    = true, +    $path_is_webdir                   = false, +    $logmode                          = 'default', +    $logpath                          = 'absent', +    $documentroot_owner               = apache, +    $documentroot_group               = 0, +    $documentroot_mode                = 0640, +    $run_mode                         = 'normal', +    $run_uid                          = 'absent', +    $run_gid                          = 'absent', +    $options                          = 'absent', +    $additional_options               = 'absent', +    $default_charset                  = 'absent', +    $mod_security                     = false, +    $mod_security_relevantonly        = true, +    $mod_security_rules_to_disable    = [], +    $mod_security_additional_options  = 'absent', +    $ssl_mode                         = false, +    $vhost_mode                       = 'template', +    $vhost_source                     = 'absent', +    $vhost_destination                = 'absent', +    $htpasswd_file                    = 'absent', +    $htpasswd_path                    = 'absent', +    $ldap_auth                        = false, +    $ldap_user                        = 'any', +    $dav_db_dir                       = 'absent' +){ +  ::apache::vhost::davdbdir{$name: +    ensure              => $ensure, +    dav_db_dir          => $dav_db_dir, +    documentroot_owner  => $documentroot_owner, +    documentroot_group  => $documentroot_group, +    documentroot_mode   => $documentroot_mode, +    run_mode            => $run_mode, +    run_uid             => $run_uid, +  } + +  if $manage_webdir { +    # create webdir +    ::apache::vhost::webdir{$name: +      ensure              => $ensure, +      path                => $path, +      owner               => $owner, +      group               => $group, +      run_mode            => $run_mode, +      datadir             => false, +      documentroot_owner  => $documentroot_owner, +      documentroot_group  => $documentroot_group, +      documentroot_mode   => $documentroot_mode, +    } +  } + +  if $run_mode == 'static-itk' { +    notice('static-itk mode is not possible for webdav vhosts, rewriting it to proxy-itk') +    $real_run_mode = 'proxy-itk' +  } else { +    $real_run_mode = $run_mode +  } + +  # create vhost configuration file +  ::apache::vhost{$name: +    ensure                          => $ensure, +    configuration                   => $configuration, +    path                            => $path, +    path_is_webdir                  => $path_is_webdir, +    logpath                         => $logpath, +    logmode                         => $logmode, +    template_partial                => 'apache/vhosts/webdav/partial.erb', +    vhost_mode                      => $vhost_mode, +    vhost_source                    => $vhost_source, +    vhost_destination               => $vhost_destination, +    domain                          => $domain, +    domainalias                     => $domainalias, +    server_admin                    => $server_admin, +    run_mode                        => $real_run_mode, +    run_uid                         => $run_uid, +    run_gid                         => $run_gid, +    options                         => $options, +    additional_options              => $additional_options, +    default_charset                 => $default_charset, +    ssl_mode                        => $ssl_mode, +    htpasswd_file                   => $htpasswd_file, +    htpasswd_path                   => $htpasswd_path, +    ldap_auth                       => $ldap_auth, +    ldap_user                       => $ldap_user, +    mod_security                    => $mod_security, +    mod_security_relevantonly       => $mod_security_relevantonly, +    mod_security_rules_to_disable   => $mod_security_rules_to_disable, +    mod_security_additional_options => $mod_security_additional_options, +  } +} + diff --git a/puppet/modules/apache/manifests/vhost/webdir.pp b/puppet/modules/apache/manifests/vhost/webdir.pp new file mode 100644 index 00000000..e0e25464 --- /dev/null +++ b/puppet/modules/apache/manifests/vhost/webdir.pp @@ -0,0 +1,130 @@ +# create webdir +define apache::vhost::webdir( +  $ensure               = present, +  $path                 = 'absent', +  $owner                = root, +  $group                = apache, +  $mode                 = 0640, +  $run_mode             = 'normal', +  $manage_docroot       = true, +  $datadir              = true, +  $documentroot_owner   = root, +  $documentroot_group   = apache, +  $documentroot_mode    = 0640, +  $documentroot_recurse = false +){ +  $real_path = $path ? { +    'absent' => $::operatingsystem ? { +      openbsd => "/var/www/htdocs/${name}", +      default => "/var/www/vhosts/${name}" +    }, +    default => $path +  } + +  if (($run_mode =~ /^(static\-|proxy\-)?itk$/) or $run_mode == 'fcgid') and ($mode == '0640'){ +    $real_mode = 0644 +  } else { +    $real_mode = $mode +  } + +  $documentroot = "${real_path}/www" +  $logdir = "${real_path}/logs" + +  if $owner == 'apache' { +    $real_owner = $::operatingsystem ? { +      openbsd => 'www', +      debian  => 'www-data', +      default => $owner +    } +  } else { +      $real_owner = $owner +  } +  if $group == 'apache' { +    $real_group = $::operatingsystem ? { +      openbsd => 'www', +      debian  => 'www-data', +      default => $group +    } +  } else { +    $real_group = $group +  } + +  if $documentroot_owner == 'apache' { +    $real_documentroot_owner = $::operatingsystem ? { +      openbsd => 'www', +      debian  => 'www-data', +      default => $documentroot_owner +    } +  } else { +    $real_documentroot_owner = $documentroot_owner +  } +  if $documentroot_group == 'apache' { +    $real_documentroot_group = $::operatingsystem ? { +      openbsd => 'www', +      debian  => 'www-data', +      default => $documentroot_group +    } +  } else { +    $real_documentroot_group = $documentroot_group +  } +  case $ensure { +    absent: { +      exec{"cleanup_webdir_${real_path}": +        command => "rm -rf ${real_path}", +        onlyif  => "test -d  ${real_path}", +        before  => File[$real_path], +      } +      file{$real_path: +        ensure  => absent, +        purge   => true, +        recurse => true, +        force   => true; +      } +    } +    default: { +      file{ +        $real_path: +          ensure  => directory, +          require => Anchor['apache::basic_dirs::ready'], +          owner   => $real_owner, +          group   => $real_group, +          mode    => $real_mode; +        $logdir: +          ensure  => directory, +          before  => Service['apache'], +          owner   => $real_documentroot_owner, +          group   => $real_documentroot_group, +          mode    => '0660'; +        "${real_path}/private": +          ensure  => directory, +          owner   => $real_documentroot_owner, +          group   => $real_documentroot_group, +          mode    => '0600'; +      } +      if $manage_docroot { +        file{$documentroot: +          ensure  => directory, +          before  => Service['apache'], +          recurse => $documentroot_recurse, +          owner   => $real_documentroot_owner, +          group   => $real_documentroot_group, +          mode    => $documentroot_mode; +        } +      } +      if $datadir { +        file{"${real_path}/data": +          ensure  => directory, +          owner   => $real_documentroot_owner, +          group   => $real_documentroot_group, +          mode    => '0640'; +        } +      } +      case $::operatingsystem { +        centos: { include apache::logrotate::centos::vhosts } +        default: { #nothing +        } +      } +    } +  } +} + diff --git a/puppet/modules/apache/manifests/webdav.pp b/puppet/modules/apache/manifests/webdav.pp new file mode 100644 index 00000000..75219c90 --- /dev/null +++ b/puppet/modules/apache/manifests/webdav.pp @@ -0,0 +1,8 @@ +# manifests/webdav.pp + +class apache::webdav { +    file{'/var/www/webdavlock': +        ensure => directory, +        owner => apache, group => 0, mode => 0700; +    } +} diff --git a/puppet/modules/apache/manifests/worker.pp b/puppet/modules/apache/manifests/worker.pp new file mode 100644 index 00000000..9a7b3be4 --- /dev/null +++ b/puppet/modules/apache/manifests/worker.pp @@ -0,0 +1,5 @@ +class apache::worker inherits apache { +  case $::operatingsystem { +    centos: { include ::apache::centos::worker } +  } +} diff --git a/puppet/modules/apache/spec/classes/init_spec.rb b/puppet/modules/apache/spec/classes/init_spec.rb new file mode 100644 index 00000000..baf26470 --- /dev/null +++ b/puppet/modules/apache/spec/classes/init_spec.rb @@ -0,0 +1,43 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'apache', :type => 'class' do +  describe 'with standard' do +    #puppet-rspec bug +    #it { should compile.with_all_deps } + +    it { should contain_class('apache::base') } +    it { should_not contain_class('apache::status') } +    it { should_not contain_class('shorewall::rules::http') } +    it { should_not contain_class('apache::ssl') } +    context 'on centos' do +      let(:facts) { +        { +          :operatingsystem => 'CentOS', +        } +      } +      it { should contain_class('apache::centos') } +    end +  end +  describe 'with params' do +    let(:facts) { +      { +        :concat_basedir => '/var/lib/puppet/concat' +      } +    } +    let(:params){ +      { +        :manage_shorewall => true, +        # there is puppet-librarian bug in using that module +        #:manage_munin     => true, +        :ssl              => true, +      } +    } +    #puppet-rspec bug +    #it { should compile.with_all_deps } + +    it { should contain_class('apache::base') } +    it { should_not contain_class('apache::status') } +    it { should contain_class('shorewall::rules::http') } +    it { should contain_class('apache::ssl') } +  end +end diff --git a/puppet/modules/apache/spec/defines/vhost_file_spec.rb b/puppet/modules/apache/spec/defines/vhost_file_spec.rb new file mode 100644 index 00000000..ed9ac5e2 --- /dev/null +++ b/puppet/modules/apache/spec/defines/vhost_file_spec.rb @@ -0,0 +1,131 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'apache::vhost::file', :type => 'define' do +  let(:title){ 'example.com' } +  let(:facts){ +    { +      :fqdn => 'apache.example.com', +    } +  } +  let(:pre_condition) { +    'include apache' +  } +  describe 'with standard' do +    it { should contain_file('example.com.conf').with( +      :ensure  => 'present', +      :source  => [ "puppet:///modules/site_apache/vhosts.d/apache.example.com/example.com.conf", +                  "puppet:///modules/site_apache/vhosts.d//example.com.conf", +                  "puppet:///modules/site_apache/vhosts.d/./example.com.conf", +                  "puppet:///modules/site_apache/vhosts.d//example.com.conf", +                  "puppet:///modules/site_apache/vhosts.d/example.com.conf", +                  "puppet:///modules/apache/vhosts.d/./example.com.conf", +                  "puppet:///modules/apache/vhosts.d//example.com.conf", +                  "puppet:///modules/apache/vhosts.d/example.com.conf" ], +      :path    => '/etc/apache2/vhosts.d/example.com.conf', +      :require => 'File[vhosts_dir]', +      :notify  => 'Service[apache]', +      :owner   => 'root', +      :group   => 0, +      :mode    => '0644', +    )} +    it { should_not contain_file('/var/www/htpasswds/example.com') } +    it { should_not contain_class('apache::includes') } +    it { should_not contain_class('apache::mod_macro') } +    it { should_not contain_class('apache::noiplog') } +    it { should_not contain_class('apache::itk::lock') } +    it { should_not contain_class('mod_security::itk_plus') } +    it { should_not contain_class('mod_security') } +  end +  context 'on centos' do +    let(:facts){ +      { +        :fqdn                       => 'apache.example.com', +        :operatingsystem            => 'CentOS', +        :operatingsystemmajrelease  => '7', +      } +    } +    it { should contain_file('example.com.conf').with( +      :ensure  => 'present', +      :source  => [ "puppet:///modules/site_apache/vhosts.d/apache.example.com/example.com.conf", +                  "puppet:///modules/site_apache/vhosts.d//example.com.conf", +                  "puppet:///modules/site_apache/vhosts.d/CentOS.7/example.com.conf", +                  "puppet:///modules/site_apache/vhosts.d/CentOS/example.com.conf", +                  "puppet:///modules/site_apache/vhosts.d/example.com.conf", +                  "puppet:///modules/apache/vhosts.d/CentOS.7/example.com.conf", +                  "puppet:///modules/apache/vhosts.d/CentOS/example.com.conf", +                  "puppet:///modules/apache/vhosts.d/example.com.conf" ], +      :path    => '/etc/httpd/vhosts.d/example.com.conf', +      :require => 'File[vhosts_dir]', +      :notify  => 'Service[apache]', +      :owner   => 'root', +      :group   => 0, +      :mode    => '0644', +    )} +    it { should_not contain_file('/var/www/htpasswds/example.com') } +    it { should_not contain_class('apache::includes') } +    it { should_not contain_class('apache::mod_macro') } +    it { should_not contain_class('apache::noiplog') } +    it { should_not contain_class('apache::itk::lock') } +    it { should_not contain_class('mod_security::itk_plus') } +    it { should_not contain_class('mod_security') } +    context 'with params' do +      let(:params) { +        { +          :vhost_destination => '/tmp/a/example.com.conf', +          :vhost_source      => 'modules/my_module/example.com.conf', +          :htpasswd_file     => true, +          :do_includes       => true, +          :mod_security      => true, +          :use_mod_macro     => true, +          :logmode           => 'anonym', +        } +      } +      it { should contain_file('example.com.conf').with( +        :ensure  => 'present', +        :source  => 'puppet:///modules/my_module/example.com.conf', +        :path    => '/tmp/a/example.com.conf', +        :require => 'File[vhosts_dir]', +        :notify  => 'Service[apache]', +        :owner   => 'root', +        :group   => 0, +        :mode    => '0644', +      )} +      it { should contain_file('/var/www/htpasswds/example.com').with( +        :source  => [ "puppet:///modules/site_apache/htpasswds/apache.example.com/example.com", +                      "puppet:///modules/site_apache/htpasswds//example.com", +                      "puppet:///modules/site_apache/htpasswds/example.com" ], +        :owner   => 'root', +        :group   => 0, +        :mode    => '0644', +      )} +      it { should contain_class('apache::includes') } +      it { should contain_class('apache::mod_macro') } +      it { should contain_class('apache::noiplog') } +      it { should_not contain_class('apache::itk::lock') } +      it { should_not contain_class('mod_security::itk_plus') } +      it { should contain_class('mod_security') } +    end +    context 'with content' do +      let(:params) { +        { +          :content => "<VirtualHost *:80>\n  Servername example.com\n</VirtualHost>" +        } +      } +      it { should contain_file('example.com.conf').with( +        :ensure  => 'present', +        :path    => '/etc/httpd/vhosts.d/example.com.conf', +        :require => 'File[vhosts_dir]', +        :notify  => 'Service[apache]', +        :owner   => 'root', +        :group   => 0, +        :mode    => '0644', +      )} +      it { should contain_file('example.com.conf').with_content( +"<VirtualHost *:80> +  Servername example.com +</VirtualHost>" +      )} +      it { should_not contain_file('/var/www/htpasswds/example.com') } +    end +  end +end diff --git a/puppet/modules/apache/spec/defines/vhost_php_drupal_spec.rb b/puppet/modules/apache/spec/defines/vhost_php_drupal_spec.rb new file mode 100644 index 00000000..5256746d --- /dev/null +++ b/puppet/modules/apache/spec/defines/vhost_php_drupal_spec.rb @@ -0,0 +1,187 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'apache::vhost::php::drupal', :type => 'define' do +  let(:title){ 'example.com' } +  let(:facts){ +    { +      :fqdn => 'apache.example.com', +      :operatingsystem            => 'CentOS', +      :operatingsystemmajrelease  => '7', +    } +  } +  describe 'with standard' do +    it { should contain_file('/etc/cron.d/drupal_cron_example.com').with( +      :content => "0   *   *   *   *   apache wget -O - -q -t 1 http://example.com/cron.php\n", +      :owner   => 'root', +      :group   => 0, +      :mode    => '0644', +    )} +    # only test the differences from the default +    it { should contain_apache__vhost__php__webapp('example.com').with( +      :manage_directories => false, +      :template_partial   => 'apache/vhosts/php_drupal/partial.erb', +      :manage_config      => false, +      :php_settings       => { +        'magic_quotes_gpc'              => 0, +        'register_globals'              => 0, +        'session.auto_start'            => 0, +        'mbstring.http_input'           => 'pass', +        'mbstring.http_output'          => 'pass', +        'mbstring.encoding_translation' => 0, +      } +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + + +    php_admin_flag engine on +    php_admin_value error_log /var/www/vhosts/example.com/logs/php_error_log +    php_admin_value magic_quotes_gpc 0 +    php_admin_value mbstring.encoding_translation 0 +    php_admin_value mbstring.http_input pass +    php_admin_value mbstring.http_output pass +    php_admin_value open_basedir /var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com +    php_admin_value register_globals 0 +    php_admin_flag safe_mode on +    php_admin_value session.auto_start 0 +    php_admin_value session.save_path /var/www/session.save_path/example.com +    php_admin_value upload_tmp_dir /var/www/upload_tmp_dir/example.com + +    # Protect files and directories from prying eyes. +    <FilesMatch \"\\.(engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(\\.php)?|xtmpl)$|^(code-style\\.pl|Entries.*|Repository|Root|Tag|Template)$\"> +      Order allow,deny +    </FilesMatch> + +    # Customized error messages. +    ErrorDocument 404 /index.php + +    RewriteEngine on +    RewriteCond %{REQUEST_FILENAME} !-f +    RewriteCond %{REQUEST_FILENAME} !-d +    RewriteRule ^(.*)$ index.php?q=$1 [L,QSA] +  </Directory> +  <Directory \"/var/www/vhosts/example.com/www/files/\"> +    SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 +    Options None +    Options +FollowSymLinks +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with mod_fcgid' do +    let(:params){ +      { +        :run_mode => 'fcgid', +        :run_uid  => 'foo', +        :run_gid  => 'bar', +      } +    } +    it { should contain_file('/etc/cron.d/drupal_cron_example.com').with( +      :content => "0   *   *   *   *   apache wget -O - -q -t 1 http://example.com/cron.php\n", +      :owner   => 'root', +      :group   => 0, +      :mode    => '0644', +    )} +    # only test variables that are tuned +    it { should contain_apache__vhost__php__webapp('example.com').with( +      :run_mode                       => 'fcgid', +      :run_uid                        => 'foo', +      :run_gid                        => 'bar', +      :manage_directories             => false, +      :template_partial               => 'apache/vhosts/php_drupal/partial.erb', +      :manage_config                  => false, +      :php_settings                   => { +        'magic_quotes_gpc'              => 0, +        'register_globals'              => 0, +        'session.auto_start'            => 0, +        'mbstring.http_input'           => 'pass', +        'mbstring.http_output'          => 'pass', +        'mbstring.encoding_translation' => 0, +      }, +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <IfModule mod_fcgid.c> +    SuexecUserGroup foo bar +    FcgidMaxRequestsPerProcess 5000 +    FCGIWrapper /var/www/mod_fcgid-starters/example.com/example.com-starter .php +    AddHandler fcgid-script .php +  </IfModule> + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +ExecCGI + + +    # Protect files and directories from prying eyes. +    <FilesMatch \"\\.(engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(\\.php)?|xtmpl)$|^(code-style\\.pl|Entries.*|Repository|Root|Tag|Template)$\"> +      Order allow,deny +    </FilesMatch> + +    # Customized error messages. +    ErrorDocument 404 /index.php + +    RewriteEngine on +    RewriteCond %{REQUEST_FILENAME} !-f +    RewriteCond %{REQUEST_FILENAME} !-d +    RewriteRule ^(.*)$ index.php?q=$1 [L,QSA] +  </Directory> +  <Directory \"/var/www/vhosts/example.com/www/files/\"> +    SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 +    Options None +    Options +FollowSymLinks +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +end diff --git a/puppet/modules/apache/spec/defines/vhost_php_gallery2_spec.rb b/puppet/modules/apache/spec/defines/vhost_php_gallery2_spec.rb new file mode 100644 index 00000000..9f2325e9 --- /dev/null +++ b/puppet/modules/apache/spec/defines/vhost_php_gallery2_spec.rb @@ -0,0 +1,162 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'apache::vhost::php::gallery2', :type => 'define' do +  let(:title){ 'example.com' } +  let(:facts){ +    { +      :fqdn => 'apache.example.com', +      :operatingsystem            => 'CentOS', +      :operatingsystemmajrelease  => '7', +    } +  } +  describe 'with standard' do +    # only test the differences from the default +    it { should contain_apache__vhost__php__webapp('example.com').with( +      :manage_directories             => true, +      :template_partial               => 'apache/vhosts/php_gallery2/partial.erb', +      :php_settings                   => { +        'safe_mode'         => 'Off', +        'output_buffering'  => 'Off', +      }, +      :manage_config                  => true, +      :config_webwriteable            => false, +      :config_file                    => 'config.php', +    )} +    it { should contain_file('/var/www/vhosts/example.com/data/upload').with( +      :ensure => 'directory', +      :owner  => 'apache', +      :group  => 0, +      :mode   => '0660', +    )} +    it { should contain_file('/var/www/vhosts/example.com/data/gdata').with( +      :ensure => 'directory', +      :owner  => 'apache', +      :group  => 0, +      :mode   => '0660', +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + +    php_admin_flag engine on +    php_admin_value error_log /var/www/vhosts/example.com/logs/php_error_log +    php_admin_value open_basedir /var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com +    php_admin_flag output_buffering off +    php_admin_flag safe_mode off +    php_admin_value session.save_path /var/www/session.save_path/example.com +    php_admin_value upload_tmp_dir /var/www/upload_tmp_dir/example.com + + + +    # Always rewrite login's +    # Source: http://gallery.menalto.com/node/30558 +    RewriteEngine On +    RewriteCond %{HTTPS} !=on +    RewriteCond %{HTTP:X-Forwarded-Proto} !=https +    RewriteCond %{HTTP_COOKIE} ^GALLERYSID= [OR] +    RewriteCond %{QUERY_STRING} subView=core\\.UserLogin +    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R,L] +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine Off +    SecAuditEngine Off +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with mod_fcgid' do +    let(:params){ +      { +        :run_mode => 'fcgid', +        :run_uid  => 'foo', +        :run_gid  => 'bar', +      } +    } +    # only test variables that are tuned +    it { should contain_apache__vhost__php__webapp('example.com').with( +      :run_mode                       => 'fcgid', +      :run_uid                        => 'foo', +      :run_gid                        => 'bar', +      :template_partial               => 'apache/vhosts/php_gallery2/partial.erb', +      :php_settings                   => { +        'safe_mode'         => 'Off', +        'output_buffering'  => 'Off', +      }, +      :manage_directories             => true, +      :manage_config                  => true, +      :config_webwriteable            => false, +      :config_file                    => 'config.php', +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <IfModule mod_fcgid.c> +    SuexecUserGroup foo bar +    FcgidMaxRequestsPerProcess 5000 +    FCGIWrapper /var/www/mod_fcgid-starters/example.com/example.com-starter .php +    AddHandler fcgid-script .php +  </IfModule> + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +ExecCGI + + + +    # Always rewrite login's +    # Source: http://gallery.menalto.com/node/30558 +    RewriteEngine On +    RewriteCond %{HTTPS} !=on +    RewriteCond %{HTTP:X-Forwarded-Proto} !=https +    RewriteCond %{HTTP_COOKIE} ^GALLERYSID= [OR] +    RewriteCond %{QUERY_STRING} subView=core\\.UserLogin +    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R,L] +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine Off +    SecAuditEngine Off +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +end diff --git a/puppet/modules/apache/spec/defines/vhost_php_joomla_spec.rb b/puppet/modules/apache/spec/defines/vhost_php_joomla_spec.rb new file mode 100644 index 00000000..000154de --- /dev/null +++ b/puppet/modules/apache/spec/defines/vhost_php_joomla_spec.rb @@ -0,0 +1,279 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'apache::vhost::php::joomla', :type => 'define' do +  let(:title){ 'example.com' } +  let(:facts){ +    { +      :fqdn => 'apache.example.com', +      :operatingsystem            => 'CentOS', +      :operatingsystemmajrelease  => '7', +    } +  } +  describe 'with standard' do +    it { should contain_class('apache::include::joomla') } +    # only test the differences from the default +    it { should contain_apache__vhost__php__webapp('example.com').with( +      :template_partial               => 'apache/vhosts/php_joomla/partial.erb', +      :php_settings                   => { +        'allow_url_fopen'   => 'on', +        'allow_url_include' => 'off', +      }, +      :manage_config                  => true, +      :config_webwriteable            => false, +      :config_file                    => 'configuration.php', +      :manage_directories             => true, +      :managed_directories            =>  [ "/var/www/vhosts/example.com/www/administrator/backups", +                                            "/var/www/vhosts/example.com/www/administrator/components", +                                            "/var/www/vhosts/example.com/www/administrator/language", +                                            "/var/www/vhosts/example.com/www/administrator/modules", +                                            "/var/www/vhosts/example.com/www/administrator/templates", +                                            "/var/www/vhosts/example.com/www/components", +                                            "/var/www/vhosts/example.com/www/dmdocuments", +                                            "/var/www/vhosts/example.com/www/images", +                                            "/var/www/vhosts/example.com/www/language", +                                            "/var/www/vhosts/example.com/www/media", +                                            "/var/www/vhosts/example.com/www/modules", +                                            "/var/www/vhosts/example.com/www/plugins", +                                            "/var/www/vhosts/example.com/www/templates", +                                            "/var/www/vhosts/example.com/www/cache", +                                            "/var/www/vhosts/example.com/www/tmp", +                                            "/var/www/vhosts/example.com/www/administrator/cache" ], +      :mod_security_additional_options => " +    # http://optics.csufresno.edu/~kriehn/fedora/fedora_files/f9/howto/modsecurity.html +    # Exceptions for Joomla Root Directory +    <LocationMatch \"^/\"> +        SecRuleRemoveById 950013 +    </LocationMatch> + +    # Exceptions for Joomla Administration Panel +    SecRule REQUEST_FILENAME \"/administrator/index2.php\" \"id:1199400,allow,phase:1,nolog,ctl:ruleEngine=Off\" + +    # Exceptions for Joomla Component Expose +    <LocationMatch \"^/components/com_expose/expose/manager/amfphp/gateway.php\"> +        SecRuleRemoveById 960010 +    </LocationMatch> +" +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + +    php_admin_flag allow_url_fopen on +    php_admin_flag allow_url_include off +    php_admin_flag engine on +    php_admin_value error_log /var/www/vhosts/example.com/logs/php_error_log +    php_admin_value open_basedir /var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com +    php_admin_flag safe_mode on +    php_admin_value session.save_path /var/www/session.save_path/example.com +    php_admin_value upload_tmp_dir /var/www/upload_tmp_dir/example.com +  + + +    Include include.d/joomla.inc +  </Directory> + +  <Directory \"/var/www/vhosts/example.com/www/administrator/\"> +    RewriteEngine on + +    # Rewrite URLs to https that go for the admin area +    RewriteCond %{REMOTE_ADDR} !^127\\.[0-9]+\\.[0-9]+\\.[0-9]+$ +    RewriteCond %{HTTPS} !=on +    RewriteCond %{REQUEST_URI} (.*/administrator/.*) +    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R] +  </Directory> + +  # Deny various directories that +  # shouldn't be webaccessible +  <Directory \"/var/www/vhosts/example.com/www/tmp/\"> +    Deny From All +  </Directory> +  <Directory \"/var/www/vhosts/example.com/www/logs/\"> +    Deny From All +  </Directory> +  <Directory \"/var/www/vhosts/example.com/www/cli/\"> +    Deny From All +  </Directory> + + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log + +     +    # http://optics.csufresno.edu/~kriehn/fedora/fedora_files/f9/howto/modsecurity.html +    # Exceptions for Joomla Root Directory +    <LocationMatch \"^/\"> +        SecRuleRemoveById 950013 +    </LocationMatch> + +    # Exceptions for Joomla Administration Panel +    SecRule REQUEST_FILENAME \"/administrator/index2.php\" \"id:1199400,allow,phase:1,nolog,ctl:ruleEngine=Off\" + +    # Exceptions for Joomla Component Expose +    <LocationMatch \"^/components/com_expose/expose/manager/amfphp/gateway.php\"> +        SecRuleRemoveById 960010 +    </LocationMatch> + +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with mod_fcgid' do +    let(:params){ +      { +        :run_mode => 'fcgid', +        :run_uid  => 'foo', +        :run_gid  => 'bar', +      } +    } +    it { should contain_class('apache::include::joomla') } +    # only test the differences from the default +    it { should contain_apache__vhost__php__webapp('example.com').with( +      :run_mode                       => 'fcgid', +      :run_uid                        => 'foo', +      :run_gid                        => 'bar', +      :template_partial               => 'apache/vhosts/php_joomla/partial.erb', +      :php_settings                   => { +        'allow_url_fopen'   => 'on', +        'allow_url_include' => 'off', +      }, +      :manage_config                  => true, +      :config_webwriteable            => false, +      :config_file                    => 'configuration.php', +      :manage_directories             => true, +      :managed_directories            =>  [ "/var/www/vhosts/example.com/www/administrator/backups", +                                            "/var/www/vhosts/example.com/www/administrator/components", +                                            "/var/www/vhosts/example.com/www/administrator/language", +                                            "/var/www/vhosts/example.com/www/administrator/modules", +                                            "/var/www/vhosts/example.com/www/administrator/templates", +                                            "/var/www/vhosts/example.com/www/components", +                                            "/var/www/vhosts/example.com/www/dmdocuments", +                                            "/var/www/vhosts/example.com/www/images", +                                            "/var/www/vhosts/example.com/www/language", +                                            "/var/www/vhosts/example.com/www/media", +                                            "/var/www/vhosts/example.com/www/modules", +                                            "/var/www/vhosts/example.com/www/plugins", +                                            "/var/www/vhosts/example.com/www/templates", +                                            "/var/www/vhosts/example.com/www/cache", +                                            "/var/www/vhosts/example.com/www/tmp", +                                            "/var/www/vhosts/example.com/www/administrator/cache" ], +      :mod_security_additional_options => " +    # http://optics.csufresno.edu/~kriehn/fedora/fedora_files/f9/howto/modsecurity.html +    # Exceptions for Joomla Root Directory +    <LocationMatch \"^/\"> +        SecRuleRemoveById 950013 +    </LocationMatch> + +    # Exceptions for Joomla Administration Panel +    SecRule REQUEST_FILENAME \"/administrator/index2.php\" \"id:1199400,allow,phase:1,nolog,ctl:ruleEngine=Off\" + +    # Exceptions for Joomla Component Expose +    <LocationMatch \"^/components/com_expose/expose/manager/amfphp/gateway.php\"> +        SecRuleRemoveById 960010 +    </LocationMatch> +" +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <IfModule mod_fcgid.c> +    SuexecUserGroup foo bar +    FcgidMaxRequestsPerProcess 5000 +    FCGIWrapper /var/www/mod_fcgid-starters/example.com/example.com-starter .php +    AddHandler fcgid-script .php +  </IfModule> + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +ExecCGI +  + + +    Include include.d/joomla.inc +  </Directory> + +  <Directory \"/var/www/vhosts/example.com/www/administrator/\"> +    RewriteEngine on + +    # Rewrite URLs to https that go for the admin area +    RewriteCond %{REMOTE_ADDR} !^127\\.[0-9]+\\.[0-9]+\\.[0-9]+$ +    RewriteCond %{HTTPS} !=on +    RewriteCond %{REQUEST_URI} (.*/administrator/.*) +    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R] +  </Directory> + +  # Deny various directories that +  # shouldn't be webaccessible +  <Directory \"/var/www/vhosts/example.com/www/tmp/\"> +    Deny From All +  </Directory> +  <Directory \"/var/www/vhosts/example.com/www/logs/\"> +    Deny From All +  </Directory> +  <Directory \"/var/www/vhosts/example.com/www/cli/\"> +    Deny From All +  </Directory> + + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log + +     +    # http://optics.csufresno.edu/~kriehn/fedora/fedora_files/f9/howto/modsecurity.html +    # Exceptions for Joomla Root Directory +    <LocationMatch \"^/\"> +        SecRuleRemoveById 950013 +    </LocationMatch> + +    # Exceptions for Joomla Administration Panel +    SecRule REQUEST_FILENAME \"/administrator/index2.php\" \"id:1199400,allow,phase:1,nolog,ctl:ruleEngine=Off\" + +    # Exceptions for Joomla Component Expose +    <LocationMatch \"^/components/com_expose/expose/manager/amfphp/gateway.php\"> +        SecRuleRemoveById 960010 +    </LocationMatch> + +  </IfModule> + +</VirtualHost> +" +)} +  end +end diff --git a/puppet/modules/apache/spec/defines/vhost_php_standard_spec.rb b/puppet/modules/apache/spec/defines/vhost_php_standard_spec.rb new file mode 100644 index 00000000..159d4b81 --- /dev/null +++ b/puppet/modules/apache/spec/defines/vhost_php_standard_spec.rb @@ -0,0 +1,534 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'apache::vhost::php::standard', :type => 'define' do +  let(:title){ 'example.com' } +  let(:facts){ +    { +      :fqdn => 'apache.example.com', +      :operatingsystem            => 'CentOS', +      :operatingsystemmajrelease  => '7', +    } +  } +  describe 'with standard' do +    # only test variables that are tuned +    it { should contain_apache__vhost__webdir('example.com') } +    it { should_not contain_class('mod_fcgid') } +    it { should_not contain_class('php::mod_fcgid') } +    it { should_not contain_class('apache::include::mod_fcgid') } +    it { should_not contain_class('php::scl::php54') } +    it { should_not contain_class('php::scl::php55') } +    it { should_not contain_class('php::extensions::smarty') } +    it { should contain_class('php') } +    it { should_not contain_mod_fcgid__starter('example.com') } + +    # only test variables that are tuned +    it { should contain_apache__vhost__phpdirs('example.com').with( +      :php_upload_tmp_dir     => '/var/www/upload_tmp_dir/example.com', +      :php_session_save_path  => '/var/www/session.save_path/example.com', +    )} +    # only test variables that are tuned +    it { should contain_apache__vhost('example.com').with( +      :template_partial  => 'apache/vhosts/php/partial.erb', +      :passing_extension => 'php' +    )} + +    it { should have_apache__vhost__php__safe_mode_bin_resource_count(0) } +    it { should contain_file('/var/www/vhosts/example.com/bin').with( +      :ensure  => 'absent', +      :recurse => true, +      :force   => true, +      :purge   => true, +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + +    php_admin_flag engine on +    php_admin_value error_log /var/www/vhosts/example.com/logs/php_error_log +    php_admin_value open_basedir /var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com +    php_admin_flag safe_mode on +    php_admin_value session.save_path /var/www/session.save_path/example.com +    php_admin_value upload_tmp_dir /var/www/upload_tmp_dir/example.com + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with standard and params' do +    let(:params) { +      { +        :php_settings => { +          'safe_mode' => 'Off', +        } +      } +    } +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + +    php_admin_flag engine on +    php_admin_value error_log /var/www/vhosts/example.com/logs/php_error_log +    php_admin_value open_basedir /var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com +    php_admin_flag safe_mode off +    php_admin_value session.save_path /var/www/session.save_path/example.com +    php_admin_value upload_tmp_dir /var/www/upload_tmp_dir/example.com + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with mod_fcgid' do +    let(:params){ +      { +        :run_mode => 'fcgid', +        :run_uid  => 'foo', +        :run_gid  => 'bar', +      } +    } +    # only test variables that are tuned +    it { should contain_apache__vhost__webdir('example.com') } +    it { should contain_class('mod_fcgid') } +    it { should contain_class('php::mod_fcgid') } +    it { should contain_class('apache::include::mod_fcgid') } +    it { should_not contain_class('php::scl::php54') } +    it { should_not contain_class('php::scl::php55') } +    it { should_not contain_class('php::extensions::smarty') } +    it { should contain_mod_fcgid__starter('example.com').with( +      :tmp_dir          => false, +      :cgi_type         => 'php', +      :cgi_type_options => { +        "engine"            =>"On", +        "upload_tmp_dir"    =>"/var/www/upload_tmp_dir/example.com", +        "session.save_path" =>"/var/www/session.save_path/example.com", +        "error_log"         =>"/var/www/vhosts/example.com/logs/php_error_log", +        "safe_mode"         =>"On", +        "safe_mode_gid"     =>"On", +        "safe_mode_exec_dir"=>:undef, +        "default_charset"   =>:undef, +        "open_basedir"      =>"/var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com" +      }, +      :owner            => 'foo', +      :group            => 'bar', +      :notify           => 'Service[apache]', +    ) } + +    # only test variables that are tuned +    it { should contain_apache__vhost__phpdirs('example.com').with( +      :php_upload_tmp_dir     => '/var/www/upload_tmp_dir/example.com', +      :php_session_save_path  => '/var/www/session.save_path/example.com', +    )} +    # only test variables that are tuned +    it { should contain_apache__vhost('example.com').with( +      :template_partial  => 'apache/vhosts/php/partial.erb', +      :passing_extension => 'php' +    )} + +    it { should have_apache__vhost__php__safe_mode_bin_resource_count(0) } +    it { should contain_file('/var/www/vhosts/example.com/bin').with( +      :ensure  => 'absent', +      :recurse => true, +      :force   => true, +      :purge   => true, +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <IfModule mod_fcgid.c> +    SuexecUserGroup foo bar +    FcgidMaxRequestsPerProcess 5000 +    FCGIWrapper /var/www/mod_fcgid-starters/example.com/example.com-starter .php +    AddHandler fcgid-script .php +  </IfModule> + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +ExecCGI + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with mod_fcgid scl 5.4' do +    let(:pre_condition){ 'include yum::prerequisites' } +    let(:params){ +      { +        :run_mode         => 'fcgid', +        :run_uid          => 'foo', +        :run_gid          => 'bar', +        :php_installation => 'scl54', +      } +    } +    # only test variables that are tuned +    it { should contain_apache__vhost__webdir('example.com') } +    it { should contain_class('mod_fcgid') } +    it { should contain_class('php::mod_fcgid') } +    it { should contain_class('apache::include::mod_fcgid') } +    it { should contain_class('php::scl::php54') } +    it { should_not contain_class('php::scl::php55') } +    it { should_not contain_class('php::extensions::smarty') } +    it { should contain_mod_fcgid__starter('example.com').with( +      :tmp_dir          => false, +      :cgi_type         => 'php', +      :cgi_type_options => { +        "engine"            =>"On", +        "upload_tmp_dir"    =>"/var/www/upload_tmp_dir/example.com", +        "session.save_path" =>"/var/www/session.save_path/example.com", +        "error_log"         =>"/var/www/vhosts/example.com/logs/php_error_log", +        "safe_mode"         =>:undef, +        "safe_mode_gid"     =>:undef, +        "safe_mode_exec_dir"=>:undef, +        "default_charset"   =>:undef, +        "open_basedir"      =>"/var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com" +      }, +      :binary           => '/opt/rh/php54/root/usr/bin/php-cgi', +      :additional_cmds  => 'source /opt/rh/php54/enable', +      :rc               => '/opt/rh/php54/root/etc', +      :owner            => 'foo', +      :group            => 'bar', +      :notify           => 'Service[apache]', +    ) } + +    # only test variables that are tuned +    it { should contain_apache__vhost__phpdirs('example.com').with( +      :php_upload_tmp_dir     => '/var/www/upload_tmp_dir/example.com', +      :php_session_save_path  => '/var/www/session.save_path/example.com', +    )} +    # only test variables that are tuned +    it { should contain_apache__vhost('example.com').with( +      :template_partial  => 'apache/vhosts/php/partial.erb', +      :passing_extension => 'php' +    )} + +    it { should have_apache__vhost__php__safe_mode_bin_resource_count(0) } +    it { should contain_file('/var/www/vhosts/example.com/bin').with( +      :ensure  => 'absent', +      :recurse => true, +      :force   => true, +      :purge   => true, +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <IfModule mod_fcgid.c> +    SuexecUserGroup foo bar +    FcgidMaxRequestsPerProcess 5000 +    FCGIWrapper /var/www/mod_fcgid-starters/example.com/example.com-starter .php +    AddHandler fcgid-script .php +  </IfModule> + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +ExecCGI + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with mod_fcgid with scl55' do +    let(:pre_condition){ 'include yum::prerequisites' } +    let(:params){ +      { +        :run_mode         => 'fcgid', +        :run_uid          => 'foo', +        :run_gid          => 'bar', +        :php_installation => 'scl55', +      } +    } +    # only test variables that are tuned +    it { should contain_apache__vhost__webdir('example.com') } +    it { should contain_class('mod_fcgid') } +    it { should contain_class('php::mod_fcgid') } +    it { should contain_class('apache::include::mod_fcgid') } +    it { should_not contain_class('php::scl::php54') } +    it { should contain_class('php::scl::php55') } +    it { should_not contain_class('php::extensions::smarty') } +    it { should contain_mod_fcgid__starter('example.com').with( +      :tmp_dir          => false, +      :cgi_type         => 'php', +      :cgi_type_options => { +        "engine"            =>"On", +        "upload_tmp_dir"    =>"/var/www/upload_tmp_dir/example.com", +        "session.save_path" =>"/var/www/session.save_path/example.com", +        "error_log"         =>"/var/www/vhosts/example.com/logs/php_error_log", +        "safe_mode"         =>:undef, +        "safe_mode_gid"     =>:undef, +        "safe_mode_exec_dir"=>:undef, +        "default_charset"   =>:undef, +        "open_basedir"      =>"/var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com" +      }, +      :binary           => '/opt/rh/php55/root/usr/bin/php-cgi', +      :additional_cmds  => 'source /opt/rh/php55/enable', +      :rc               => '/opt/rh/php55/root/etc', +      :owner            => 'foo', +      :group            => 'bar', +      :notify           => 'Service[apache]', +    ) } + +    # only test variables that are tuned +    it { should contain_apache__vhost__phpdirs('example.com').with( +      :php_upload_tmp_dir     => '/var/www/upload_tmp_dir/example.com', +      :php_session_save_path  => '/var/www/session.save_path/example.com', +    )} +    # only test variables that are tuned +    it { should contain_apache__vhost('example.com').with( +      :template_partial  => 'apache/vhosts/php/partial.erb', +      :passing_extension => 'php' +    )} + +    it { should have_apache__vhost__php__safe_mode_bin_resource_count(0) } +    it { should contain_file('/var/www/vhosts/example.com/bin').with( +      :ensure  => 'absent', +      :recurse => true, +      :force   => true, +      :purge   => true, +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <IfModule mod_fcgid.c> +    SuexecUserGroup foo bar +    FcgidMaxRequestsPerProcess 5000 +    FCGIWrapper /var/www/mod_fcgid-starters/example.com/example.com-starter .php +    AddHandler fcgid-script .php +  </IfModule> + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +ExecCGI + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with mod_fcgid and params' do +    let(:params){ +      { +        :run_mode     => 'fcgid', +        :run_uid      => 'foo', +        :run_gid      => 'bar', +        :logmode      => 'nologs', +        :php_options  => { +          'smarty'              => true, +          'pear'                => true, +          'safe_mode_exec_bins' => ['/usr/bin/cat'], +        } +      } +    } +    # only test variables that are tuned +    it { should contain_apache__vhost__webdir('example.com') } +    it { should contain_class('mod_fcgid') } +    it { should contain_class('php::mod_fcgid') } +    it { should contain_class('apache::include::mod_fcgid') } +    it { should_not contain_class('php::scl::php54') } +    it { should_not contain_class('php::scl::php55') } +    it { should contain_class('php::extensions::smarty') } +    it { should contain_mod_fcgid__starter('example.com').with( +      :tmp_dir          => false, +      :cgi_type         => 'php', +      :cgi_type_options => { +        "engine"            =>"On", +        "upload_tmp_dir"    =>"/var/www/upload_tmp_dir/example.com", +        "session.save_path" =>"/var/www/session.save_path/example.com", +        "error_log"         =>:undef, +        "safe_mode"         =>"On", +        "safe_mode_gid"     =>"On", +        "safe_mode_exec_dir"=>"/var/www/vhosts/example.com/bin", +        "default_charset"   =>:undef, +        "open_basedir"      =>"/usr/share/php/Smarty/:/usr/share/pear/:/var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com" +      }, +      :owner            => 'foo', +      :group            => 'bar', +      :notify           => 'Service[apache]', +    ) } + +    # only test variables that are tuned +    it { should contain_apache__vhost__phpdirs('example.com').with( +      :php_upload_tmp_dir     => '/var/www/upload_tmp_dir/example.com', +      :php_session_save_path  => '/var/www/session.save_path/example.com', +    )} +    # only test variables that are tuned +    it { should contain_apache__vhost('example.com').with( +      :template_partial  => 'apache/vhosts/php/partial.erb', +      :passing_extension => 'php' +    )} + +    it { should have_apache__vhost__php__safe_mode_bin_resource_count(1) } +    it { should contain_apache__vhost__php__safe_mode_bin('example.com@/usr/bin/cat').with( +      :ensure => 'present', +      :path   => '/var/www/vhosts/example.com/bin', +    )} +    it { should contain_file('/var/www/vhosts/example.com/bin').with( +      :ensure  => 'directory', +      :owner   => 'apache', +      :group   => '0', +      :recurse => true, +      :force   => true, +      :purge   => true, +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /dev/null +  CustomLog /dev/null + + + +  <IfModule mod_fcgid.c> +    SuexecUserGroup foo bar +    FcgidMaxRequestsPerProcess 5000 +    FCGIWrapper /var/www/mod_fcgid-starters/example.com/example.com-starter .php +    AddHandler fcgid-script .php +  </IfModule> + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +ExecCGI + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +end diff --git a/puppet/modules/apache/spec/defines/vhost_php_webapp_spec.rb b/puppet/modules/apache/spec/defines/vhost_php_webapp_spec.rb new file mode 100644 index 00000000..bdebb14c --- /dev/null +++ b/puppet/modules/apache/spec/defines/vhost_php_webapp_spec.rb @@ -0,0 +1,261 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'apache::vhost::php::webapp', :type => 'define' do +  let(:title){ 'example.com' } +  let(:facts){ +    { +      :fqdn => 'apache.example.com', +      :operatingsystem            => 'CentOS', +      :operatingsystemmajrelease  => '7', +    } +  } +  describe 'with standard' do +    let(:params){ +      { +        :manage_config    => false, +        :template_partial => 'apache/vhosts/php/partial.erb', +      } +    } +    # only test variables that are tuned +    it { should have_apache__file__rw_resource_count(0) } +    it { should_not contain_apache__vhost__file__documentrootfile('configurationfile_example.com') } +    it { should contain_apache__vhost__php__standard('example.com') } +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + +    php_admin_flag engine on +    php_admin_value error_log /var/www/vhosts/example.com/logs/php_error_log +    php_admin_value open_basedir /var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com +    php_admin_flag safe_mode on +    php_admin_value session.save_path /var/www/session.save_path/example.com +    php_admin_value upload_tmp_dir /var/www/upload_tmp_dir/example.com + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with mod_fcgid' do +    let(:params){ +      { +        :manage_config    => false, +        :template_partial => 'apache/vhosts/php/partial.erb', +        :run_mode => 'fcgid', +        :run_uid  => 'foo', +        :run_gid  => 'bar', +      } +    } +    # only test variables that are tuned +    it { should have_apache__file__rw_resource_count(0) } +    it { should_not contain_apache__vhost__file__documentrootfile('configurationfile_example.com') } +    it { should contain_apache__vhost__php__standard('example.com') } +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <IfModule mod_fcgid.c> +    SuexecUserGroup foo bar +    FcgidMaxRequestsPerProcess 5000 +    FCGIWrapper /var/www/mod_fcgid-starters/example.com/example.com-starter .php +    AddHandler fcgid-script .php +  </IfModule> + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +ExecCGI + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  context 'with config file and directories' do +    describe 'with standard' do +      let(:params){ +        { +          :manage_config        => true, +          :managed_directories  => [ '/tmp/a', '/tmp/b' ], +          :config_file          => 'config.php', +          :template_partial     => 'apache/vhosts/php/partial.erb', +        } +      } +      # only test variables that are tuned +      it { should have_apache__file__rw_resource_count(2) } +      it { should contain_apache__file__rw('/tmp/a').with( +        :owner => 'apache', +        :group => 0, +      )} +      it { should contain_apache__file__rw('/tmp/b').with( +        :owner => 'apache', +        :group => 0, +      )} +      it { should contain_apache__vhost__file__documentrootfile('configurationfile_example.com').with( +        :documentroot => '/var/www/vhosts/example.com/www', +        :filename     => 'config.php', +        :thedomain    => 'example.com', +        :owner        => 'apache', +        :group        => 0, +        :mode         => '0440', +      ) } +      it { should contain_apache__vhost__php__standard('example.com') } +      # go deeper in the catalog and test the produced template +      it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + +    php_admin_flag engine on +    php_admin_value error_log /var/www/vhosts/example.com/logs/php_error_log +    php_admin_value open_basedir /var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com +    php_admin_flag safe_mode on +    php_admin_value session.save_path /var/www/session.save_path/example.com +    php_admin_value upload_tmp_dir /var/www/upload_tmp_dir/example.com + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +    end +    describe 'with standard but writable' do +      let(:params){ +        { +          :manage_config        => true, +          :config_webwriteable  => true, +          :managed_directories  => [ '/tmp/a', '/tmp/b' ], +          :config_file          => 'config.php', +          :template_partial     => 'apache/vhosts/php/partial.erb', +        } +      } +      # only test variables that are tuned +      it { should have_apache__file__rw_resource_count(2) } +      it { should contain_apache__file__rw('/tmp/a').with( +        :owner => 'apache', +        :group => 0, +      )} +      it { should contain_apache__file__rw('/tmp/b').with( +        :owner => 'apache', +        :group => 0, +      )} +      it { should contain_apache__vhost__file__documentrootfile('configurationfile_example.com').with( +        :documentroot => '/var/www/vhosts/example.com/www', +        :filename     => 'config.php', +        :thedomain    => 'example.com', +        :owner        => 'apache', +        :group        => 0, +        :mode         => '0660', +      ) } +      it { should contain_apache__vhost__php__standard('example.com') } +      # go deeper in the catalog and test the produced template +      it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + +    php_admin_flag engine on +    php_admin_value error_log /var/www/vhosts/example.com/logs/php_error_log +    php_admin_value open_basedir /var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com +    php_admin_flag safe_mode on +    php_admin_value session.save_path /var/www/session.save_path/example.com +    php_admin_value upload_tmp_dir /var/www/upload_tmp_dir/example.com + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +    end +  end +end diff --git a/puppet/modules/apache/spec/defines/vhost_php_wordpress_spec.rb b/puppet/modules/apache/spec/defines/vhost_php_wordpress_spec.rb new file mode 100644 index 00000000..203f9690 --- /dev/null +++ b/puppet/modules/apache/spec/defines/vhost_php_wordpress_spec.rb @@ -0,0 +1,171 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'apache::vhost::php::wordpress', :type => 'define' do +  let(:title){ 'example.com' } +  let(:facts){ +    { +      :fqdn => 'apache.example.com', +      :operatingsystem            => 'CentOS', +      :operatingsystemmajrelease  => '7', +    } +  } +  describe 'with standard' do +    # only test the differences from the default +    it { should contain_apache__vhost__php__webapp('example.com').with( +      :mod_security_rules_to_disable  => ["960010", "950018"], +      :manage_directories             => true, +      :managed_directories            => '/var/www/vhosts/example.com/www/wp-content', +      :template_partial               => 'apache/vhosts/php_wordpress/partial.erb', +      :manage_config                  => true, +      :config_webwriteable            => false, +      :config_file                    => 'wp-config.php', +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride FileInfo + +    php_admin_flag engine on +    php_admin_value error_log /var/www/vhosts/example.com/logs/php_error_log +    php_admin_value open_basedir /var/www/vhosts/example.com/www:/var/www/vhosts/example.com/data:/var/www/upload_tmp_dir/example.com:/var/www/session.save_path/example.com +    php_admin_flag safe_mode on +    php_admin_value session.save_path /var/www/session.save_path/example.com +    php_admin_value upload_tmp_dir /var/www/upload_tmp_dir/example.com + + +  </Directory> + + +  # fixes: http://git.zx2c4.com/w3-total-fail/tree/w3-total-fail.sh +  <Directory \"/var/www/vhosts/example.com/www/wp-content/w3tc/dbcache\"> +    Deny From All +  </Directory> + +  # simple wp-login brute force protection +  # http://www.frameloss.org/2013/04/26/even-easier-brute-force-login-protection-for-wordpress/ +  RewriteEngine On +  RewriteCond %{HTTP_COOKIE} !359422a82c97336dc082622faf72013a8e857bfd +  RewriteRule ^/wp-login.php /wordpress-login-576a63fdc98202e7c7283713f2ddfee334bf13ee.php [R,L] +  <Location /wordpress-login-576a63fdc98202e7c7283713f2ddfee334bf13ee.php> +    CookieTracking on +    CookieExpires 30 +    CookieName 359422a82c97336dc082622faf72013a8e857bfd +  </Location> +  RewriteRule ^/wordpress-login-576a63fdc98202e7c7283713f2ddfee334bf13ee.php /wp-login.php [NE] + + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log + +    SecRuleRemoveById \"960010\" +    SecRuleRemoveById \"950018\" +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with mod_fcgid' do +    let(:params){ +      { +        :run_mode => 'fcgid', +        :run_uid  => 'foo', +        :run_gid  => 'bar', +      } +    } +    # only test variables that are tuned +    it { should contain_apache__vhost__php__webapp('example.com').with( +      :run_mode                       => 'fcgid', +      :run_uid                        => 'foo', +      :run_gid                        => 'bar', +      :template_partial               => 'apache/vhosts/php_wordpress/partial.erb', +      :mod_security_rules_to_disable  => ["960010", "950018"], +      :manage_directories             => true, +      :managed_directories            => '/var/www/vhosts/example.com/www/wp-content', +      :manage_config                  => true, +      :config_webwriteable            => false, +      :config_file                    => 'wp-config.php', +    )} +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ +  DirectoryIndex index.htm index.html index.php + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <IfModule mod_fcgid.c> +    SuexecUserGroup foo bar +    FcgidMaxRequestsPerProcess 5000 +    FCGIWrapper /var/www/mod_fcgid-starters/example.com/example.com-starter .php +    AddHandler fcgid-script .php +  </IfModule> + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride FileInfo +    Options  +ExecCGI + + +  </Directory> + + +  # fixes: http://git.zx2c4.com/w3-total-fail/tree/w3-total-fail.sh +  <Directory \"/var/www/vhosts/example.com/www/wp-content/w3tc/dbcache\"> +    Deny From All +  </Directory> + +  # simple wp-login brute force protection +  # http://www.frameloss.org/2013/04/26/even-easier-brute-force-login-protection-for-wordpress/ +  RewriteEngine On +  RewriteCond %{HTTP_COOKIE} !359422a82c97336dc082622faf72013a8e857bfd +  RewriteRule ^/wp-login.php /wordpress-login-576a63fdc98202e7c7283713f2ddfee334bf13ee.php [R,L] +  <Location /wordpress-login-576a63fdc98202e7c7283713f2ddfee334bf13ee.php> +    CookieTracking on +    CookieExpires 30 +    CookieName 359422a82c97336dc082622faf72013a8e857bfd +  </Location> +  RewriteRule ^/wordpress-login-576a63fdc98202e7c7283713f2ddfee334bf13ee.php /wp-login.php [NE] + + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log + +    SecRuleRemoveById \"960010\" +    SecRuleRemoveById \"950018\" +  </IfModule> + +</VirtualHost> +" +)} +  end +end diff --git a/puppet/modules/apache/spec/defines/vhost_spec.rb b/puppet/modules/apache/spec/defines/vhost_spec.rb new file mode 100644 index 00000000..051ad0d4 --- /dev/null +++ b/puppet/modules/apache/spec/defines/vhost_spec.rb @@ -0,0 +1,202 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'apache::vhost', :type => 'define' do +  let(:title){ 'example.com' } +  let(:facts){ +    { +      :fqdn => 'apache.example.com', +      :operatingsystem            => 'CentOS', +      :operatingsystemmajrelease  => '7', +    } +  } +  let(:pre_condition) { +    'include apache' +  } +  describe 'with standard' do +    it { should contain_apache__vhost__template('example.com').with( +      :ensure         => 'present', +      :do_includes    => false, +      :run_mode       => 'normal', +      :ssl_mode       => false, +      :logmode        => 'default', +      :mod_security   => true, +      :htpasswd_file  => 'absent', +      :htpasswd_path  => 'absent', +      :use_mod_macro  => false, +    )} +    # go deeper in the catalog and the test the produced content from the template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with params' do +    let(:params){ +      { +        :do_includes    => true, +        :ssl_mode       => true, +        :logmode        => 'anonym', +        :mod_security   => false, +        :htpasswd_file  => true, +      } +    } +    it { should contain_apache__vhost__template('example.com').with( +      :ensure                           => 'present', +      :path                             => 'absent', +      :path_is_webdir                   => false, +      :logpath                          => 'absent', +      :logmode                          => 'anonym', +      :logprefix                        => '', +      :domain                           => 'absent', +      :domainalias                      => 'absent', +      :server_admin                     => 'absent', +      :allow_override                   => 'None', +      :do_includes                      => true, +      :options                          => 'absent', +      :additional_options               => 'absent', +      :default_charset                  => 'absent', +      :php_settings                     => {}, +      :php_options                      => {}, +      :run_mode                         => 'normal', +      :run_uid                          => 'absent', +      :run_gid                          => 'absent', +      :template_partial                 => 'apache/vhosts/static/partial.erb', +      :ssl_mode                         => true, +      :htpasswd_file                    => true, +      :htpasswd_path                    => 'absent', +      :ldap_auth                        => false, +      :ldap_user                        => 'any', +      :mod_security                     => false, +      :mod_security_relevantonly        => true, +      :mod_security_rules_to_disable    => [], +      :mod_security_additional_options  => 'absent', +      :use_mod_macro                    => false, +      :passing_extension                => 'absent', +      :gempath                          => 'absent', +    )} +    # go deeper in the catalog and the test the produced content from the template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ + + +  ErrorLog /dev/null +  CustomLog /var/www/vhosts/example.com/logs/access_log noip + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +Includes +    AuthType Basic +    AuthName \"Access fuer example.com\" +    AuthUserFile /var/www/htpasswds/example.com +    require valid-user + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine Off +    SecAuditEngine Off +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +<VirtualHost *:443 > + +  Include include.d/defaults.inc +  Include include.d/ssl_defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ + + +  ErrorLog /dev/null +  CustomLog /var/www/vhosts/example.com/logs/access_log noip + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +Includes +    AuthType Basic +    AuthName \"Access fuer example.com\" +    AuthUserFile /var/www/htpasswds/example.com +    require valid-user + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine Off +    SecAuditEngine Off +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with params II' do +    let(:params){ +      { +        :vhost_mode     => 'file', +      } +    } +    it { should_not contain_apache__vhost__template('example.com') } +    it { should contain_apache__vhost__file('example.com').with( +      :ensure             => 'present', +      :vhost_source       => 'absent', +      :vhost_destination  => 'absent', +      :do_includes        => false, +      :run_mode       => 'normal', +      :mod_security   => true, +      :htpasswd_file  => 'absent', +      :htpasswd_path  => 'absent', +      :use_mod_macro  => false, +    )} +  end +  describe 'with wrong vhost_mode' do +    let(:params){ +      { +        :vhost_mode     => 'foo', +      } +    } +    it { expect { should compile }.to raise_error(Puppet::Error, /No such vhost_mode: foo defined for example.com\./) +    } +  end +end diff --git a/puppet/modules/apache/spec/defines/vhost_static_spec.rb b/puppet/modules/apache/spec/defines/vhost_static_spec.rb new file mode 100644 index 00000000..37891bb5 --- /dev/null +++ b/puppet/modules/apache/spec/defines/vhost_static_spec.rb @@ -0,0 +1,54 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'apache::vhost::static', :type => 'define' do +  let(:title){ 'example.com' } +  let(:facts){ +    { +      :fqdn => 'apache.example.com', +      :operatingsystem            => 'CentOS', +      :operatingsystemmajrelease  => '7', +    } +  } +  let(:pre_condition) { +    'include apache' +  } +  describe 'with standard' do +    # only test the relevant options +    it { should contain_apache__vhost__webdir('example.com').with( +      :datadir  => false, +    )} +    it { should contain_apache__vhost('example.com') } +    # go deeper in the catalog and test the produced template +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine Off +    SecAuditEngine Off +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +end diff --git a/puppet/modules/apache/spec/defines/vhost_template_spec.rb b/puppet/modules/apache/spec/defines/vhost_template_spec.rb new file mode 100644 index 00000000..96fb9ac3 --- /dev/null +++ b/puppet/modules/apache/spec/defines/vhost_template_spec.rb @@ -0,0 +1,297 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'apache::vhost::template', :type => 'define' do +  let(:title){ 'example.com' } +  let(:facts){ +    { +      :fqdn => 'apache.example.com', +      :operatingsystem            => 'CentOS', +      :operatingsystemmajrelease  => '7', +    } +  } +  let(:pre_condition) { +    'include apache' +  } +  describe 'with standard' do +    it { should contain_apache__vhost__file('example.com').with( +      :ensure         => 'present', +      :do_includes    => false, +      :run_mode       => 'normal', +      :ssl_mode       => false, +      :logmode        => 'default', +      :mod_security   => true, +      :htpasswd_file  => 'absent', +      :htpasswd_path  => 'absent', +      :use_mod_macro  => false, +    )} +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log combined + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with params' do +    let(:params){ +      { +        :do_includes    => true, +        :ssl_mode       => true, +        :logmode        => 'anonym', +        :mod_security   => false, +        :htpasswd_file  => true, +      } +    } +    it { should contain_apache__vhost__file('example.com').with( +      :ensure         => 'present', +      :do_includes    => true, +      :run_mode       => 'normal', +      :ssl_mode       => true, +      :logmode        => 'anonym', +      :mod_security   => false, +      :htpasswd_file  => true, +      :htpasswd_path  => 'absent', +      :use_mod_macro  => false, +    )} +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ + + +  ErrorLog /dev/null +  CustomLog /var/www/vhosts/example.com/logs/access_log noip + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +Includes +    AuthType Basic +    AuthName \"Access fuer example.com\" +    AuthUserFile /var/www/htpasswds/example.com +    require valid-user + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine Off +    SecAuditEngine Off +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +<VirtualHost *:443 > + +  Include include.d/defaults.inc +  Include include.d/ssl_defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ + + +  ErrorLog /dev/null +  CustomLog /var/www/vhosts/example.com/logs/access_log noip + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +Includes +    AuthType Basic +    AuthName \"Access fuer example.com\" +    AuthUserFile /var/www/htpasswds/example.com +    require valid-user + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine Off +    SecAuditEngine Off +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with params II' do +    let(:params){ +      { +        :do_includes    => true, +        :ssl_mode       => 'force', +        :logmode        => 'semianonym', +        :mod_security   => false, +        :htpasswd_file  => true, +      } +    } +    it { should contain_apache__vhost__file('example.com').with( +      :ensure         => 'present', +      :do_includes    => true, +      :run_mode       => 'normal', +      :ssl_mode       => 'force', +      :logmode        => 'semianonym', +      :mod_security   => false, +      :htpasswd_file  => true, +      :htpasswd_path  => 'absent', +      :use_mod_macro  => false, +    )} +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:80 > + +  Include include.d/defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log noip + + + +  RewriteEngine On +  RewriteCond %{HTTPS} !=on +  RewriteCond %{HTTP:X-Forwarded-Proto} !=https +  RewriteRule (.*) https://%{SERVER_NAME}$1 [R=permanent,L] +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +Includes +    AuthType Basic +    AuthName \"Access fuer example.com\" +    AuthUserFile /var/www/htpasswds/example.com +    require valid-user + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine Off +    SecAuditEngine Off +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +<VirtualHost *:443 > + +  Include include.d/defaults.inc +  Include include.d/ssl_defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ + + +  ErrorLog /var/www/vhosts/example.com/logs/error_log +  CustomLog /var/www/vhosts/example.com/logs/access_log noip + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None +    Options  +Includes +    AuthType Basic +    AuthName \"Access fuer example.com\" +    AuthUserFile /var/www/htpasswds/example.com +    require valid-user + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine Off +    SecAuditEngine Off +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +  describe 'with params III' do +    let(:params){ +      { +        :do_includes    => false, +        :ssl_mode       => 'only', +        :logmode        => 'nologs', +        :mod_security   => true, +        :htpasswd_file  => 'absent', +      } +    } +    it { should contain_apache__vhost__file('example.com').with( +      :ensure         => 'present', +      :do_includes    => false, +      :run_mode       => 'normal', +      :ssl_mode       => 'only', +      :logmode        => 'nologs', +      :mod_security   => true, +      :htpasswd_file  => 'absent', +      :htpasswd_path  => 'absent', +      :use_mod_macro  => false, +    )} +    it { should contain_apache__vhost__file('example.com').with_content( +"<VirtualHost *:443 > + +  Include include.d/defaults.inc +  Include include.d/ssl_defaults.inc +  ServerName example.com +  DocumentRoot /var/www/vhosts/example.com/www/ + + +  ErrorLog /dev/null +  CustomLog /dev/null + + + +  <Directory \"/var/www/vhosts/example.com/www/\"> +    AllowOverride None + + +  </Directory> + +  <IfModule mod_security2.c> +    SecRuleEngine On +    SecAuditEngine RelevantOnly +    SecAuditLogType Concurrent +    SecAuditLogStorageDir /var/www/vhosts/example.com/logs/ +    SecAuditLog /var/www/vhosts/example.com/logs/mod_security_audit.log +    SecDebugLog /var/www/vhosts/example.com/logs/mod_security_debug.log +  </IfModule> + +</VirtualHost> +" +)} +  end +end diff --git a/puppet/modules/apache/spec/functions/guess_apache_version.rb b/puppet/modules/apache/spec/functions/guess_apache_version.rb new file mode 100644 index 00000000..b57a7a0f --- /dev/null +++ b/puppet/modules/apache/spec/functions/guess_apache_version.rb @@ -0,0 +1,50 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'guess_apache_version function' do + +  #let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + +  it "should exist" do +    expect(Puppet::Parser::Functions.function("guess_apache_version")).to eq("function_guess_apache_version") +  end + +  context 'on debian 7.8' do +    let(:facts) do +      { +        :operatingsystem => 'Debian', +        :operatingsystemrelease => '7.8' +      } +    end +    it "should return 2.2" do +      result = scope.function_guess_apache_version([]) +      expect(result).to(eq('2.2')) +    end +  end + +  context 'on debian 8.0' do +    let(:facts) do +      { +        :operatingsystem => 'Debian', +        :operatingsystemrelease => '8.0' +      } +    end +    it "should return 2.4" do +      result = scope.function_guess_apache_version([]) +      expect(result).to(eq('2.4')) +    end +  end + +  context 'on ubuntu 15.10' do +    let(:facts) do +      { +        :operatingsystem => 'Ubuntu', +        :operatingsystemrelease => '15.10' +      } +    end +    it "should return 2.4" do +      result = scope.function_guess_apache_version([]) +      expect(result).to(eq('2.4')) +    end +  end + +end diff --git a/puppet/modules/apache/spec/spec_helper.rb b/puppet/modules/apache/spec/spec_helper.rb new file mode 100644 index 00000000..381f9720 --- /dev/null +++ b/puppet/modules/apache/spec/spec_helper.rb @@ -0,0 +1,13 @@ +require 'puppetlabs_spec_helper/module_spec_helper' +require 'rake' + +fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures')) + +RSpec.configure do |c| +  c.module_path = File.join(fixture_path, 'modules') +  c.manifest_dir = File.join(fixture_path, 'manifests') +  c.pattern = FileList[c.pattern].exclude(/^spec\/fixtures/) +end + +Puppet::Util::Log.level = :warning +Puppet::Util::Log.newdestination(:console) diff --git a/puppet/modules/apache/templates/default/default_index.erb b/puppet/modules/apache/templates/default/default_index.erb new file mode 100644 index 00000000..b35ecd91 --- /dev/null +++ b/puppet/modules/apache/templates/default/default_index.erb @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> +<head> +  <title><%= scope.lookupvar('::hostname') %></title> +  <meta http-equiv="content-type" content="text/html; charset=utf-8" /> +</head> +<body> +  <h1> No page @ this location</h1> +  <p> +    <small><em><%= scope.lookupvar('::hostname') %></em></small> +  </p> +</body> +</html> diff --git a/puppet/modules/apache/templates/include.d/ssl_defaults.inc.erb b/puppet/modules/apache/templates/include.d/ssl_defaults.inc.erb new file mode 100644 index 00000000..77f8e77a --- /dev/null +++ b/puppet/modules/apache/templates/include.d/ssl_defaults.inc.erb @@ -0,0 +1,78 @@ +#   SSL Engine Switch: +#   Enable/Disable SSL for this virtual host. +SSLEngine on + +#   SSL Protocol support: +# List the enable protocol levels with which clients will be able to +# connect.  Disable SSLv2 access by default: +SSLProtocol All -SSLv2 -SSLv3 + +#   SSL Cipher Suite: +# List the ciphers that the client is permitted to negotiate. +# See the mod_ssl documentation for a complete list. +SSLCipherSuite "<%= scope.lookupvar('apache::ssl_cipher_suite') %>" + +SSLHonorCipherOrder on + +#   SSL Engine Options: +#   Set various options for the SSL engine. +#   o FakeBasicAuth: +#     Translate the client X.509 into a Basic Authorisation.  This means that +#     the standard Auth/DBMAuth methods can be used for access control.  The +#     user name is the `one line' version of the client's X.509 certificate. +#     Note that no password is obtained from the user. Every entry in the user +#     file needs this password: `xxj31ZMTZzkVA'. +#   o ExportCertData: +#     This exports two additional environment variables: SSL_CLIENT_CERT and +#     SSL_SERVER_CERT. These contain the PEM-encoded certificates of the +#     server (always existing) and the client (only existing when client +#     authentication is used). This can be used to import the certificates +#     into CGI scripts. +#   o StdEnvVars: +#     This exports the standard SSL/TLS related `SSL_*' environment variables. +#     Per default this exportation is switched off for performance reasons, +#     because the extraction step is an expensive operation and is usually +#     useless for serving static content. So one usually enables the +#     exportation for CGI and SSI requests only. +#   o StrictRequire: +#     This denies access when "SSLRequireSSL" or "SSLRequire" applied even +#     under a "Satisfy any" situation, i.e. when it applies access is denied +#     and no other module can change it. +#   o OptRenegotiate: +#     This enables optimized SSL connection renegotiation handling when SSL +#     directives are used in per-directory context.  +#SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire +<Files ~ "\.(cgi|shtml|phtml|php3?)$"> +    SSLOptions +StdEnvVars +</Files> +<Directory "/var/www/cgi-bin"> +    SSLOptions +StdEnvVars +</Directory> + +#   SSL Protocol Adjustments: +#   The safe and default but still SSL/TLS standard compliant shutdown +#   approach is that mod_ssl sends the close notify alert but doesn't wait for +#   the close notify alert from client. When you need a different shutdown +#   approach you can use one of the following variables: +#   o ssl-unclean-shutdown: +#     This forces an unclean shutdown when the connection is closed, i.e. no +#     SSL close notify alert is send or allowed to received.  This violates +#     the SSL/TLS standard but is needed for some brain-dead browsers. Use +#     this when you receive I/O errors because of the standard approach where +#     mod_ssl sends the close notify alert. +#   o ssl-accurate-shutdown: +#     This forces an accurate shutdown when the connection is closed, i.e. a +#     SSL close notify alert is send and mod_ssl waits for the close notify +#     alert of the client. This is 100% SSL/TLS standard compliant, but in +#     practice often causes hanging connections with brain-dead browsers. Use +#     this only for browsers where you know that their SSL implementation +#     works correctly.  +#   Notice: Most problems of broken clients are also related to the HTTP +#   keep-alive facility, so you usually additionally want to disable +#   keep-alive for those clients, too. Use variable "nokeepalive" for this. +#   Similarly, one has to force some clients to use HTTP/1.0 to workaround +#   their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and +#   "force-response-1.0" for this. +SetEnvIf User-Agent ".*MSIE.*" \ +         nokeepalive ssl-unclean-shutdown \ +         downgrade-1.0 force-response-1.0 diff --git a/puppet/modules/apache/templates/itk_plus/CentOS/00-listen-ssl.conf.erb b/puppet/modules/apache/templates/itk_plus/CentOS/00-listen-ssl.conf.erb new file mode 100644 index 00000000..83f7beeb --- /dev/null +++ b/puppet/modules/apache/templates/itk_plus/CentOS/00-listen-ssl.conf.erb @@ -0,0 +1,6 @@ +<IfDefine HttpdLocal> +Listen 127.0.0.1:443 +</IfDefine> +<IfDefine !HttpdLocal> +Listen <%= scope.lookupvar('::ipaddress') %>:443 +</IfDefine> diff --git a/puppet/modules/apache/templates/itk_plus/CentOS/00-listen.conf.erb b/puppet/modules/apache/templates/itk_plus/CentOS/00-listen.conf.erb new file mode 100644 index 00000000..30b20466 --- /dev/null +++ b/puppet/modules/apache/templates/itk_plus/CentOS/00-listen.conf.erb @@ -0,0 +1,8 @@ +<IfDefine HttpdLocal> +Listen 127.0.0.1:80 +PidFile run/httpdlocal.pid +</IfDefine> +<IfDefine !HttpdLocal> +Listen <%= scope.lookupvar('::ipaddress') %>:80 +PidFile run/httpd.pid +</IfDefine> diff --git a/puppet/modules/apache/templates/vhosts/0-default_ssl.conf.erb b/puppet/modules/apache/templates/vhosts/0-default_ssl.conf.erb new file mode 100644 index 00000000..86e4979f --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/0-default_ssl.conf.erb @@ -0,0 +1,21 @@ +############################################################ +### This file is managed by PUPPET!                     #### +### Only modify in repo or you will loose the changes!  #### +############################################################ + +<VirtualHost *:443> +    Include include.d/defaults.inc +    Include include.d/ssl_defaults.inc +    DocumentRoot /var/www/html + +    # Use separate log files for the SSL virtual host; note that LogLevel +    # is not inherited from httpd.conf. +    ErrorLog logs/ssl_error_log +    TransferLog logs/ssl_access_log +    LogLevel warn + +<%= scope.function_templatewlv(['apache/vhosts/partials/ssl.erb', +                                {'configuration' => {}}]) %> +</VirtualHost> + +# vim: ts=4 filetype=apache diff --git a/puppet/modules/apache/templates/vhosts/default.erb b/puppet/modules/apache/templates/vhosts/default.erb new file mode 100644 index 00000000..1ef8023d --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/default.erb @@ -0,0 +1,44 @@ +<% +vhost_parts = case @ssl_mode +  when 'only' then [:ssl] +  when false,'false' then  [:normal] +  else [:normal,:ssl] +end +vhost_parts.each do |vhost_part| -%> +<VirtualHost *:<%= vhost_part == :ssl ? '443' : '80' %> > + +<%= scope.function_templatewlv(['apache/vhosts/partials/header_default.erb', +                                {'vhost_part'    => vhost_part, +                                 'configuration' => @configuration,}]) %> + +<%= scope.function_template(['apache/vhosts/partials/logs.erb']) %> + +<% if @run_mode.to_s =~ /(proxy\-|static\-)?itk/ -%> +  <IfModule mpm_itk_module> +    AssignUserId <%= "#{@run_uid} #{@run_gid}" %> +  </IfModule> + +<% elsif @run_mode.to_s == 'fcgid' -%> +  <IfModule mod_fcgid.c> +    SuexecUserGroup <%= "#{@run_uid} #{@run_gid}" %> +    FcgidMaxRequestsPerProcess 5000 +    FCGIWrapper /var/www/mod_fcgid-starters/<%= @name %>/<%= @name %>-starter .<%= @passing_extension %> +    AddHandler fcgid-script .<%= @passing_extension %> +  </IfModule> + +<% end -%> +<% if @ssl_mode == 'force' && vhost_part == :normal -%> +  RewriteEngine On +  RewriteCond %{HTTPS} !=on +  RewriteCond %{HTTP:X-Forwarded-Proto} !=https +  RewriteRule (.*) https://%{SERVER_NAME}$1 [R=permanent,L] +<% end -%> +<%= scope.function_templatewlv([@template_partial, {'vhost_part' => vhost_part } ]) %> +<% unless @template_partial == 'apache/vhosts/itk_plus/partial.erb' -%> +<%= scope.function_template(['apache/vhosts/partials/mod_security.erb']) %> +<% end -%> +<% unless @additional_options.to_s == 'absent' -%> +  <%= @additional_options %> +<% end -%> +</VirtualHost> +<% end -%> diff --git a/puppet/modules/apache/templates/vhosts/gitweb/partial.erb b/puppet/modules/apache/templates/vhosts/gitweb/partial.erb new file mode 100644 index 00000000..a8475f60 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/gitweb/partial.erb @@ -0,0 +1,16 @@ +  SetEnv GITWEB_CONFIG <%= @gitweb_config %> +  DirectoryIndex gitweb.cgi +  <Directory "<%= @documentroot %>/"> +<% if @options.to_s != 'absent' || @do_includes.to_s == 'true'-%> +    Options <% unless @options.to_s == 'absent' -%><%= @options %><% end -%><% if @do_includes.to_s == 'true' && !@options.include?('+Includes') -%> +Includes<% end -%><% unless @options.include?('+ExecCGI') -%> +ExecCGI<% end -%> +<% end -%> +    AddHandler cgi-script .cgi +    <Files gitweb.cgi> +      Options ExecCGI FollowSymLinks +      SetHandler cgi-script +    </Files> +    RewriteEngine on +    RewriteRule ^[a-zA-Z0-9_-]+.git/?(\?.)?$ /gitweb.cgi%{REQUESTURI} [L,PT] + +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> +  </Directory> diff --git a/puppet/modules/apache/templates/vhosts/itk_plus.erb b/puppet/modules/apache/templates/vhosts/itk_plus.erb new file mode 100644 index 00000000..b5461968 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/itk_plus.erb @@ -0,0 +1,6 @@ +<IfDefine HttpdLocal> +<%= scope.function_template(['apache/vhost/default.erb']) %> +</IfDefine> +<IfDefine !HttpdLocal> +<%= scope.function_templatewlv(['apache/vhost/default.erb', {'template_partial' => 'apache/vhosts/itk_plus/partial.erb' }]) %> +</IfDefine> diff --git a/puppet/modules/apache/templates/vhosts/itk_plus/partial.erb b/puppet/modules/apache/templates/vhosts/itk_plus/partial.erb new file mode 100644 index 00000000..df045433 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/itk_plus/partial.erb @@ -0,0 +1,31 @@ + +  ProxyPreserveHost On +  ProxyRequests off +<% if vhost_part == :ssl -%> +  SSLProxyEngine On +<%   if run_mode.to_s == 'static-itk' -%> +  ProxyPassMatch ^/(.*\.<%= @passing_extension %>/?.*)$ https://127.0.0.1/$1 +<%   else -%> +  ProxyPass / https://127.0.0.1/ +<%   end -%> +  ProxyPassReverse / https://127.0.0.1/ +<% else -%> +<%   if run_mode.to_s == 'static-itk' -%> +  ProxyPassMatch ^/(.*\.<%= @passing_extension %>/?.*)$ http://127.0.0.1/$1 +<%   else -%> +  ProxyPass / http://127.0.0.1/ +<%   end -%> +  ProxyPassReverse / http://127.0.0.1/ +<% end -%> + +<% if @run_mode.to_s == 'static-itk' && (@ssl_mode.to_s != 'force' || vhost_part == :ssl) -%> +  <Directory "<%= @documentroot %>/"> +    AllowOverride <%= @allow_override %> +<%   if @options.to_s != 'absent' || @do_includes.to_s == 'true' -%> +    Options <% unless @options.to_s == 'absent' -%><%= @options %><% end -%><% if @do_includes.to_s == 'true' && !@options.include?('+Includes') -%> +Includes<% end -%> +<%   end -%> +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> +  </Directory> +<% end -%> + + diff --git a/puppet/modules/apache/templates/vhosts/partials/authentication.erb b/puppet/modules/apache/templates/vhosts/partials/authentication.erb new file mode 100644 index 00000000..ed832210 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/partials/authentication.erb @@ -0,0 +1,6 @@ +<% unless @htpasswd_file.to_s == 'absent' -%> +    AuthType Basic +    AuthName "Access fuer <%= @servername %>" +    AuthUserFile <%= @real_htpasswd_path %> +    require valid-user +<% end -%> diff --git a/puppet/modules/apache/templates/vhosts/partials/header_default.erb b/puppet/modules/apache/templates/vhosts/partials/header_default.erb new file mode 100644 index 00000000..cd4d04ca --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/partials/header_default.erb @@ -0,0 +1,22 @@ +  Include include.d/defaults.inc +<% if vhost_part == :ssl -%> +  Include include.d/ssl_defaults.inc +<%= scope.function_templatewlv(['apache/vhosts/partials/ssl.erb', +                                {'configuration' => configuration}]) %> +<% end -%> +  ServerName <%= @servername %> +<% unless @serveralias.empty? || (@serveralias == 'absent') -%> +  ServerAlias <%= Array(@serveralias).sort.join(' ') %> +<% end -%> +<% unless @server_admin.empty? || (@server_admin == 'absent') -%> +  ServerAdmin <%= @server_admin %> +<% end -%> +<% unless @documentroot == 'really_absent' -%> +  DocumentRoot <%= @documentroot %>/ +<% end -%> +<% if @default_charset != 'absent' -%> +  AddDefaultCharset <%= @default_charset %> +<% end -%> +<% if @passing_extension != 'absent' -%> +  DirectoryIndex index.htm index.html index.<%= @passing_extension %> +<% end -%> diff --git a/puppet/modules/apache/templates/vhosts/partials/logs.erb b/puppet/modules/apache/templates/vhosts/partials/logs.erb new file mode 100644 index 00000000..4fe1b0a6 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/partials/logs.erb @@ -0,0 +1,18 @@ +<% case @logmode.to_s +      when 'nologs' -%> +  ErrorLog /dev/null +  CustomLog /dev/null %% +<% when 'noaccess' -%> +  ErrorLog <%= @logdir %>/<%= @logprefix %>error_log +  CustomLog /dev/null noip +<% when 'semianonym' -%> +  ErrorLog <%= @logdir %>/<%= @logprefix %>error_log +  CustomLog <%= @logdir %>/<%= @logprefix %>access_log noip +<% when 'anonym' -%> +  ErrorLog /dev/null +  CustomLog <%= @logdir %>/<%= @logprefix %>access_log noip +<% else -%> +  ErrorLog <%= @logdir %>/<%= @logprefix %>error_log +  CustomLog <%= @logdir %>/<%= @logprefix %>access_log combined +<% end -%> + diff --git a/puppet/modules/apache/templates/vhosts/partials/mod_security.erb b/puppet/modules/apache/templates/vhosts/partials/mod_security.erb new file mode 100644 index 00000000..380e78f1 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/partials/mod_security.erb @@ -0,0 +1,27 @@ +  <IfModule mod_security2.c> +<% if @mod_security.to_s == 'true' -%> +    SecRuleEngine On +<%   if @mod_security_relevantonly.to_s == 'true' -%> +    SecAuditEngine RelevantOnly +<%   else -%> +    SecAuditEngine On +<%   end -%> +<% else -%> +    SecRuleEngine Off +    SecAuditEngine Off +<% end -%> +    SecAuditLogType Concurrent +    SecAuditLogStorageDir <%= @logdir %>/ +    SecAuditLog <%= @logdir %>/mod_security_audit.log +    SecDebugLog <%= @logdir %>/mod_security_debug.log +<% unless (disabled_rules=Array(@mod_security_rules_to_disable)).empty? -%> + +<%    disabled_rules.each do |rule| -%> +    SecRuleRemoveById "<%= rule %>" +<%   end -%> +<% end -%> +<% unless (s=@mod_security_additional_options).to_s == 'absent' -%> + +    <%= s %> +<% end -%> +  </IfModule> diff --git a/puppet/modules/apache/templates/vhosts/partials/php_settings.erb b/puppet/modules/apache/templates/vhosts/partials/php_settings.erb new file mode 100644 index 00000000..74f6ecf2 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/partials/php_settings.erb @@ -0,0 +1,20 @@ +<% if @run_mode != 'fcgid' +  @php_settings.reject{|k,v| (v == :undef) || v.nil? }.keys.sort.each do |key| +    dvalue = @php_settings[key].to_s.downcase +    munged_value = if dvalue == 'true' +       'on' +      elsif dvalue == 'false' +        'off' +      elsif ['on','off'].include?(dvalue) +        dvalue +      else +        @php_settings[key] +      end + +       if ['on','off' ].include?(munged_value) -%> +    php_admin_flag <%= key %> <%= munged_value %> +<%     else -%> +    php_admin_value <%= key %> <%= munged_value %> +<%     end -%> +<%   end -%> +<% end -%> diff --git a/puppet/modules/apache/templates/vhosts/partials/ssl.erb b/puppet/modules/apache/templates/vhosts/partials/ssl.erb new file mode 100644 index 00000000..c9f39333 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/partials/ssl.erb @@ -0,0 +1,8 @@ +  SSLCertificateFile <%= configuration['ssl_certificate_file'] || scope.lookupvar('apache::default_ssl_certificate_file') %> +  SSLCertificateKeyFile <%= configuration['ssl_certificate_key_file'] || scope.lookupvar('apache::default_ssl_certificate_key_file') %> +<% if configuration['ssl_certificate_chain_file'] || scope.lookupvar('apache::default_ssl_certificate_chain_file') != 'absent' -%> +  SSLCertificateChainFile <%= configuration['ssl_certificate_chain_file'] || scope.lookupvar('apache::default_ssl_certificate_chain_file') %> +<% end -%> +<% if configuration['hsts'] -%> +  Header add Strict-Transport-Security "max-age=<%= (configuration['hsts']['age'] || 15768000) rescue 15768000 %>" +<% end -%> diff --git a/puppet/modules/apache/templates/vhosts/partials/std_override_options.erb b/puppet/modules/apache/templates/vhosts/partials/std_override_options.erb new file mode 100644 index 00000000..6d8b74f8 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/partials/std_override_options.erb @@ -0,0 +1,4 @@ +    AllowOverride <%= @allow_override %> +<% if @options.to_s != 'absent' || @do_includes.to_s == 'true' || @run_mode == 'fcgid' -%> +    Options <%- unless @options.to_s == 'absent' -%><%= @options %><% end -%><% if @do_includes.to_s == 'true' && !@options.include?('+Includes') -%> +Includes<% end -%><% if @run_mode == 'fcgid' && !@options.include?('+ExecCGI') -%> +ExecCGI<% end -%> +<% end -%> diff --git a/puppet/modules/apache/templates/vhosts/passenger/partial.erb b/puppet/modules/apache/templates/vhosts/passenger/partial.erb new file mode 100644 index 00000000..c3b63f55 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/passenger/partial.erb @@ -0,0 +1,7 @@ +  SetEnv GEM_HOME <%= @gempath %> +  <Directory <%= @documentroot %>/> +    AllowOverride <%= @allow_override %> +    Options <%- unless @options.to_s == 'absent' -%><%= @options %><%- end -%><%- unless !@options.to_s.include?('MultiViews') -%>-MultiViews<%- end -%> + +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> +  </Directory> diff --git a/puppet/modules/apache/templates/vhosts/perl/partial.erb b/puppet/modules/apache/templates/vhosts/perl/partial.erb new file mode 100644 index 00000000..8c1f0a5a --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/perl/partial.erb @@ -0,0 +1,14 @@ +  <Directory "<%= @documentroot %>/"> +<%= scope.function_template(['apache/vhosts/partials/std_override_options.erb']) %> +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> +  </Directory> + +<% unless @htpasswd_file.to_s == 'absent' -%> +  <Directory "<%= @cgi_binpath %>/"> +    AuthType Basic +    AuthName "Access fuer <%= @servername %>" +    AuthUserFile <%= @real_htpasswd_path %> +    require valid-user +  </Directory> +<% end -%> + ScriptAlias /cgi-bin/ <%= @cgi_binpath %>/ diff --git a/puppet/modules/apache/templates/vhosts/php/partial.erb b/puppet/modules/apache/templates/vhosts/php/partial.erb new file mode 100644 index 00000000..c19ae7b4 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/php/partial.erb @@ -0,0 +1,5 @@ +  <Directory "<%= @documentroot %>/"> +<%= scope.function_template(['apache/vhosts/partials/std_override_options.erb']) %> +<%= scope.function_template(['apache/vhosts/partials/php_settings.erb']) %> +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> +  </Directory> diff --git a/puppet/modules/apache/templates/vhosts/php_drupal/partial.erb b/puppet/modules/apache/templates/vhosts/php_drupal/partial.erb new file mode 100644 index 00000000..316942fd --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/php_drupal/partial.erb @@ -0,0 +1,22 @@ +  <Directory "<%= @documentroot %>/"> +<%= scope.function_template(['apache/vhosts/partials/std_override_options.erb']) %> +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> +<%= scope.function_template(['apache/vhosts/partials/php_settings.erb']) %> +    # Protect files and directories from prying eyes. +    <FilesMatch "\.(engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(code-style\.pl|Entries.*|Repository|Root|Tag|Template)$"> +      Order allow,deny +    </FilesMatch> + +    # Customized error messages. +    ErrorDocument 404 /index.php + +    RewriteEngine on +    RewriteCond %{REQUEST_FILENAME} !-f +    RewriteCond %{REQUEST_FILENAME} !-d +    RewriteRule ^(.*)$ index.php?q=$1 [L,QSA] +  </Directory> +  <Directory "<%= @documentroot %>/files/"> +    SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 +    Options None +    Options +FollowSymLinks +  </Directory> diff --git a/puppet/modules/apache/templates/vhosts/php_gallery2/partial.erb b/puppet/modules/apache/templates/vhosts/php_gallery2/partial.erb new file mode 100644 index 00000000..218c0e71 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/php_gallery2/partial.erb @@ -0,0 +1,14 @@ +  <Directory "<%= @documentroot %>/"> +<%= scope.function_template(['apache/vhosts/partials/std_override_options.erb']) %> +<%= scope.function_template(['apache/vhosts/partials/php_settings.erb']) %> +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> + +    # Always rewrite login's +    # Source: http://gallery.menalto.com/node/30558 +    RewriteEngine On +    RewriteCond %{HTTPS} !=on +    RewriteCond %{HTTP:X-Forwarded-Proto} !=https +    RewriteCond %{HTTP_COOKIE} ^GALLERYSID= [OR] +    RewriteCond %{QUERY_STRING} subView=core\.UserLogin +    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,R,L] +  </Directory> diff --git a/puppet/modules/apache/templates/vhosts/php_joomla/partial.erb b/puppet/modules/apache/templates/vhosts/php_joomla/partial.erb new file mode 100644 index 00000000..55445bfc --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/php_joomla/partial.erb @@ -0,0 +1,30 @@ +  <Directory "<%= @documentroot %>/"> +<%= scope.function_template(['apache/vhosts/partials/std_override_options.erb']) %> +<%= scope.function_template(['apache/vhosts/partials/php_settings.erb']) %>  +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> + +    Include include.d/joomla.inc +  </Directory> + +  <Directory "<%= @documentroot %>/administrator/"> +    RewriteEngine on + +    # Rewrite URLs to https that go for the admin area +    RewriteCond %{REMOTE_ADDR} !^127\.[0-9]+\.[0-9]+\.[0-9]+$ +    RewriteCond %{HTTPS} !=on +    RewriteCond %{REQUEST_URI} (.*/administrator/.*) +    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R] +  </Directory> + +  # Deny various directories that +  # shouldn't be webaccessible +  <Directory "<%= @documentroot %>/tmp/"> +    Deny From All +  </Directory> +  <Directory "<%= @documentroot %>/logs/"> +    Deny From All +  </Directory> +  <Directory "<%= @documentroot %>/cli/"> +    Deny From All +  </Directory> + diff --git a/puppet/modules/apache/templates/vhosts/php_mediawiki/partial.erb b/puppet/modules/apache/templates/vhosts/php_mediawiki/partial.erb new file mode 100644 index 00000000..1ed6ee3e --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/php_mediawiki/partial.erb @@ -0,0 +1,7 @@ +<% if @run_mode == 'fcgid' -%> +  RewriteEngine On +  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f +  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-d +  RewriteRule ^/?index.php/(.*)$ /index.php?title=$1 [PT,L,QSA] +<% end -%> +<%= scope.function_template(['apache/vhosts/php/partial.erb']) %> diff --git a/puppet/modules/apache/templates/vhosts/php_silverstripe/partial.erb b/puppet/modules/apache/templates/vhosts/php_silverstripe/partial.erb new file mode 100644 index 00000000..75a81931 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/php_silverstripe/partial.erb @@ -0,0 +1,12 @@ +  # silverstripe +  RewriteEngine On +  RewriteCond %{HTTPS} !=on +  RewriteCond %{HTTP:X-Forwarded-Proto} !=https +  RewriteRule /(Security|admin)(.*) https://%{HTTP_HOST}/admin$1$2 [L,R,NE] + +  <Directory "<%= @documentroot %>/"> +<%= scope.function_template(['apache/vhosts/partials/std_override_options.erb']) %> +<%= scope.function_template(['apache/vhosts/partials/php_settings.erb']) %> +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> +    Include include.d/silverstripe.inc +  </Directory> diff --git a/puppet/modules/apache/templates/vhosts/php_typo3/partial.erb b/puppet/modules/apache/templates/vhosts/php_typo3/partial.erb new file mode 100644 index 00000000..afb756df --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/php_typo3/partial.erb @@ -0,0 +1,10 @@ +<%= scope.function_template(['apache/vhosts/php/partial.erb']) %> +  <Directory "<%= @documentroot %>/typo3/"> +    RewriteEngine on + +    # Rewrite URLs to https that go for the admin area +    RewriteCond %{HTTPS} !=on +    RewriteCond %{HTTP:X-Forwarded-Proto} !=https +    RewriteCond %{REQUEST_URI} (.*/typo3/.*) +    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R,NE] +  </Directory> diff --git a/puppet/modules/apache/templates/vhosts/php_wordpress/partial.erb b/puppet/modules/apache/templates/vhosts/php_wordpress/partial.erb new file mode 100644 index 00000000..5e6ebd5e --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/php_wordpress/partial.erb @@ -0,0 +1,19 @@ +<%= scope.function_template(['apache/vhosts/php/partial.erb']) %> + +  # fixes: http://git.zx2c4.com/w3-total-fail/tree/w3-total-fail.sh +  <Directory "<%= @documentroot %>/wp-content/w3tc/dbcache"> +    Deny From All +  </Directory> + +  # simple wp-login brute force protection +  # http://www.frameloss.org/2013/04/26/even-easier-brute-force-login-protection-for-wordpress/ +  RewriteEngine On +  RewriteCond %{HTTP_COOKIE} !<%= cookie = scope.function_sha1([scope.function_fqdn_rand([9999999999999,@name]).to_s + "cookie"]) %> +  RewriteRule ^/wp-login.php /wordpress-login-<%= tmpuri = scope.function_sha1([scope.function_fqdn_rand([9999999999999,@name]).to_s + "wp-login"]) %>.php [R,L] +  <Location /wordpress-login-<%= tmpuri %>.php> +    CookieTracking on +    CookieExpires 30 +    CookieName <%= cookie %> +  </Location> +  RewriteRule ^/wordpress-login-<%= tmpuri %>.php /wp-login.php [NE] + diff --git a/puppet/modules/apache/templates/vhosts/proxy/partial.erb b/puppet/modules/apache/templates/vhosts/proxy/partial.erb new file mode 100644 index 00000000..0eecf820 --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/proxy/partial.erb @@ -0,0 +1,8 @@ +  <Proxy *> +    Order deny,allow +    Allow from all +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> +  </Proxy> +  ProxyRequests Off +  ProxyPass        /   <%= @options %>/ +  ProxyPassReverse /   <%= @options %>/ diff --git a/puppet/modules/apache/templates/vhosts/redirect/partial.erb b/puppet/modules/apache/templates/vhosts/redirect/partial.erb new file mode 100644 index 00000000..c8d7d11e --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/redirect/partial.erb @@ -0,0 +1 @@ +  Redirect permanent / https://<%= @options %> diff --git a/puppet/modules/apache/templates/vhosts/static/partial.erb b/puppet/modules/apache/templates/vhosts/static/partial.erb new file mode 100644 index 00000000..dc6f11ca --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/static/partial.erb @@ -0,0 +1,4 @@ +  <Directory "<%= @documentroot %>/"> +<%= scope.function_template(['apache/vhosts/partials/std_override_options.erb']) %> +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> +  </Directory> diff --git a/puppet/modules/apache/templates/vhosts/webdav/partial.erb b/puppet/modules/apache/templates/vhosts/webdav/partial.erb new file mode 100644 index 00000000..09ce632f --- /dev/null +++ b/puppet/modules/apache/templates/vhosts/webdav/partial.erb @@ -0,0 +1,21 @@ +  DAVLockDB <%= @real_dav_db_dir %>/DAVLock +  <Directory "<%= @documentroot %>/"> +    Dav on +    AllowOverride None +<% if @options.to_s != 'absent' || @do_includes.to_s == 'true' -%> +    Options <% unless @options.to_s == 'absent' -%><%= @options %><% end -%><% unless @options.include?('Indexes') -%> Indexes<%- end -%> + +<% else -%> +    Options Indexes + +<% end -%> +<%= scope.function_template(['apache/vhosts/partials/authentication.erb']) %> +<% if @ldap_auth.to_s == 'true' then -%> +    Include include.d/ldap_auth.inc +<%   unless ldap_user.to_s == 'any' -%> +    Require ldap-user <%= ldap_user.to_s %> +<%   else -%> +    Require valid-user +<%   end +   end -%> +  </Directory> diff --git a/puppet/modules/apache/templates/webfiles/autoconfig/config.shtml.erb b/puppet/modules/apache/templates/webfiles/autoconfig/config.shtml.erb new file mode 100644 index 00000000..3a3d6bb5 --- /dev/null +++ b/puppet/modules/apache/templates/webfiles/autoconfig/config.shtml.erb @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--#if expr="$SERVER_NAME = /([^.]*\.[^.]*)$/" --> +    <!--#set var="DOMAIN" value="$1" --> +<!--#endif --> + +<clientConfig version="1.1"> +  <emailProvider id="<%= @provider %>"> +    <domain><!--#echo var="DOMAIN" --></domain> +    <displayName><%= @display_name || @provider %> Mail (<!--#echo var="DOMAIN" -->)</displayName> +    <displayShortName><%= @shortname || @provider.split('.').first %></displayShortName> +    <incomingServer type="imap"> +      <hostname><%= @imap_server || "imap.#{@provider}" %></hostname> +      <port>143</port> +      <socketType>STARTTLS</socketType> +      <authentication>password-cleartext</authentication> +      <username>%EMAILADDRESS%</username> +    </incomingServer> +    <incomingServer type="imap"> +      <hostname><%= @imap_server || "imap.#{@provider}" %></hostname> +      <port>993</port> +      <socketType>SSL</socketType> +      <authentication>password-cleartext</authentication> +      <username>%EMAILADDRESS%</username> +    </incomingServer> +    <incomingServer type="pop3"> +      <hostname><%= @pop_server || "pop.#{@provider}" %></hostname> +      <port>110</port> +      <socketType>STARTTLS</socketType> +      <authentication>password-cleartext</authentication> +      <username>%EMAILADDRESS%</username> +    </incomingServer> +    <incomingServer type="pop3"> +      <hostname><%= @pop_server  || "pop.#{@provider}" %></hostname> +      <port>995</port> +      <socketType>SSL</socketType> +      <authentication>password-cleartext</authentication> +      <username>%EMAILADDRESS%</username> +    </incomingServer> +    <outgoingServer type="smtp"> +      <hostname><%= @smtp_server || "smtp.#{@provider}" %></hostname> +      <port>587</port> +      <socketType>STARTTLS</socketType> +      <authentication>password-cleartext</authentication> +      <username>%EMAILADDRESS%</username> +    </outgoingServer> +    <outgoingServer type="smtp"> +      <hostname><%= @smtp_server  || "smtp.#{@provider}"%></hostname> +      <port>465</port> +      <socketType>SSL</socketType> +      <authentication>password-cleartext</authentication> +      <username>%EMAILADDRESS%</username> +    </outgoingServer> +    <documentation url="<%= @documentation_url || "http://#{@provider}" %>"> +      <descr lang="de">Allgemeine Beschreibung der Einstellungen</descr> +      <descr lang="en">Generic settings page</descr> +    </documentation> +  </emailProvider> +</clientConfig> diff --git a/puppet/modules/apt/.gitignore b/puppet/modules/apt/.gitignore new file mode 100644 index 00000000..a54aa971 --- /dev/null +++ b/puppet/modules/apt/.gitignore @@ -0,0 +1,12 @@ +/pkg/ +/Gemfile.lock +/vendor/ +/spec/fixtures/manifests/* +/spec/fixtures/modules/* +!/spec/fixtures/modules/apt +!/spec/fixtures/modules/apt/* +/.vagrant/ +/.bundle/ +/coverage/ +/.idea/ +*.iml diff --git a/puppet/modules/apt/.gitlab-ci.yml b/puppet/modules/apt/.gitlab-ci.yml new file mode 100644 index 00000000..f7b8ecad --- /dev/null +++ b/puppet/modules/apt/.gitlab-ci.yml @@ -0,0 +1,12 @@ +before_script: +  - ruby -v +  - gem install bundler --no-ri --no-rdoc +  - bundle install --jobs $(nproc)  "${FLAGS[@]}" + +# don't fail on lint warnings +rspec: +  script: +    - bundle exec rake lint || /bin/true +    - bundle exec rake syntax +    - bundle exec rake validate +    - bundle exec rake spec diff --git a/puppet/modules/apt/Gemfile b/puppet/modules/apt/Gemfile new file mode 100644 index 00000000..8925a904 --- /dev/null +++ b/puppet/modules/apt/Gemfile @@ -0,0 +1,13 @@ +source "https://rubygems.org" + +group :test do +  gem "rake" +  gem "rspec", '< 3.2.0' +  gem "puppet", ENV['PUPPET_VERSION'] || ENV['GEM_PUPPET_VERSION'] || ENV['PUPPET_GEM_VERSION'] || '~> 3.7.0' +  gem "facter", ENV['FACTER_VERSION'] || ENV['GEM_FACTER_VERSION'] || ENV['FACTER_GEM_VERSION'] || '~> 2.2.0' +  gem "rspec-puppet" +  gem "puppetlabs_spec_helper" +  gem "metadata-json-lint" +  gem "rspec-puppet-facts" +  gem "mocha" +end diff --git a/puppet/modules/apt/LICENSE b/puppet/modules/apt/LICENSE new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/puppet/modules/apt/LICENSE @@ -0,0 +1,674 @@ +                    GNU GENERAL PUBLIC LICENSE +                       Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +                            Preamble + +  The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +  The licenses for most software and other practical works are designed +to take away your freedom to share and change the works.  By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users.  We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors.  You can apply it to +your programs, too. + +  When we speak of free software, we are referring to freedom, not +price.  Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +  To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights.  Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received.  You must make sure that they, too, receive +or can get the source code.  And you must show them these terms so they +know their rights. + +  Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +  For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software.  For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +  Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so.  This is fundamentally incompatible with the aim of +protecting users' freedom to change the software.  The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable.  Therefore, we +have designed this version of the GPL to prohibit the practice for those +products.  If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + +  Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary.  To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + +  The precise terms and conditions for copying, distribution and +modification follow. + +                       TERMS AND CONDITIONS + +  0. Definitions. + +  "This License" refers to version 3 of the GNU General Public License. + +  "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +  "The Program" refers to any copyrightable work licensed under this +License.  Each licensee is addressed as "you".  "Licensees" and +"recipients" may be individuals or organizations. + +  To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy.  The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + +  A "covered work" means either the unmodified Program or a work based +on the Program. + +  To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy.  Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +  To "convey" a work means any kind of propagation that enables other +parties to make or receive copies.  Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +  An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License.  If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +  1. Source Code. + +  The "source code" for a work means the preferred form of the work +for making modifications to it.  "Object code" means any non-source +form of a work. + +  A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +  The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form.  A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +  The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities.  However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work.  For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +  The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +  The Corresponding Source for a work in source code form is that +same work. + +  2. Basic Permissions. + +  All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met.  This License explicitly affirms your unlimited +permission to run the unmodified Program.  The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work.  This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +  You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force.  You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright.  Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +  Conveying under any other circumstances is permitted solely under +the conditions stated below.  Sublicensing is not allowed; section 10 +makes it unnecessary. + +  3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +  No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +  When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +  4. Conveying Verbatim Copies. + +  You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +  You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +  5. Conveying Modified Source Versions. + +  You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +    a) The work must carry prominent notices stating that you modified +    it, and giving a relevant date. + +    b) The work must carry prominent notices stating that it is +    released under this License and any conditions added under section +    7.  This requirement modifies the requirement in section 4 to +    "keep intact all notices". + +    c) You must license the entire work, as a whole, under this +    License to anyone who comes into possession of a copy.  This +    License will therefore apply, along with any applicable section 7 +    additional terms, to the whole of the work, and all its parts, +    regardless of how they are packaged.  This License gives no +    permission to license the work in any other way, but it does not +    invalidate such permission if you have separately received it. + +    d) If the work has interactive user interfaces, each must display +    Appropriate Legal Notices; however, if the Program has interactive +    interfaces that do not display Appropriate Legal Notices, your +    work need not make them do so. + +  A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit.  Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +  6. Conveying Non-Source Forms. + +  You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +    a) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by the +    Corresponding Source fixed on a durable physical medium +    customarily used for software interchange. + +    b) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by a +    written offer, valid for at least three years and valid for as +    long as you offer spare parts or customer support for that product +    model, to give anyone who possesses the object code either (1) a +    copy of the Corresponding Source for all the software in the +    product that is covered by this License, on a durable physical +    medium customarily used for software interchange, for a price no +    more than your reasonable cost of physically performing this +    conveying of source, or (2) access to copy the +    Corresponding Source from a network server at no charge. + +    c) Convey individual copies of the object code with a copy of the +    written offer to provide the Corresponding Source.  This +    alternative is allowed only occasionally and noncommercially, and +    only if you received the object code with such an offer, in accord +    with subsection 6b. + +    d) Convey the object code by offering access from a designated +    place (gratis or for a charge), and offer equivalent access to the +    Corresponding Source in the same way through the same place at no +    further charge.  You need not require recipients to copy the +    Corresponding Source along with the object code.  If the place to +    copy the object code is a network server, the Corresponding Source +    may be on a different server (operated by you or a third party) +    that supports equivalent copying facilities, provided you maintain +    clear directions next to the object code saying where to find the +    Corresponding Source.  Regardless of what server hosts the +    Corresponding Source, you remain obligated to ensure that it is +    available for as long as needed to satisfy these requirements. + +    e) Convey the object code using peer-to-peer transmission, provided +    you inform other peers where the object code and Corresponding +    Source of the work are being offered to the general public at no +    charge under subsection 6d. + +  A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +  A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling.  In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage.  For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product.  A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +  "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source.  The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +  If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information.  But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +  The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed.  Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +  Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +  7. Additional Terms. + +  "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law.  If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +  When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it.  (Additional permissions may be written to require their own +removal in certain cases when you modify the work.)  You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +  Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +    a) Disclaiming warranty or limiting liability differently from the +    terms of sections 15 and 16 of this License; or + +    b) Requiring preservation of specified reasonable legal notices or +    author attributions in that material or in the Appropriate Legal +    Notices displayed by works containing it; or + +    c) Prohibiting misrepresentation of the origin of that material, or +    requiring that modified versions of such material be marked in +    reasonable ways as different from the original version; or + +    d) Limiting the use for publicity purposes of names of licensors or +    authors of the material; or + +    e) Declining to grant rights under trademark law for use of some +    trade names, trademarks, or service marks; or + +    f) Requiring indemnification of licensors and authors of that +    material by anyone who conveys the material (or modified versions of +    it) with contractual assumptions of liability to the recipient, for +    any liability that these contractual assumptions directly impose on +    those licensors and authors. + +  All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10.  If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term.  If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +  If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +  Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +  8. Termination. + +  You may not propagate or modify a covered work except as expressly +provided under this License.  Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +  However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +  Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +  Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License.  If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +  9. Acceptance Not Required for Having Copies. + +  You are not required to accept this License in order to receive or +run a copy of the Program.  Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance.  However, +nothing other than this License grants you permission to propagate or +modify any covered work.  These actions infringe copyright if you do +not accept this License.  Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +  10. Automatic Licensing of Downstream Recipients. + +  Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License.  You are not responsible +for enforcing compliance by third parties with this License. + +  An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations.  If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +  You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License.  For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +  11. Patents. + +  A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based.  The +work thus licensed is called the contributor's "contributor version". + +  A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version.  For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +  Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +  In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement).  To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +  If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients.  "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +  If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +  A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License.  You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +  Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +  12. No Surrender of Others' Freedom. + +  If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License.  If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all.  For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +  13. Use with the GNU Affero General Public License. + +  Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work.  The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +  14. Revised Versions of this License. + +  The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time.  Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +  Each version is given a distinguishing version number.  If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation.  If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + +  If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +  Later license versions may give you additional or different +permissions.  However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +  15. Disclaimer of Warranty. + +  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +  16. Limitation of Liability. + +  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +  17. Interpretation of Sections 15 and 16. + +  If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +                     END OF TERMS AND CONDITIONS + +            How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + +    <one line to give the program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    This program is free software: you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation, either version 3 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program.  If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + +  If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +    <program>  Copyright (C) <year>  <name of author> +    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + +  You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + +  The GNU General Public License does not permit incorporating your program +into proprietary programs.  If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library.  If this is what you want to do, use the GNU Lesser General +Public License instead of this License.  But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/puppet/modules/apt/README b/puppet/modules/apt/README new file mode 100644 index 00000000..00db7d8e --- /dev/null +++ b/puppet/modules/apt/README @@ -0,0 +1,602 @@ + +Overview +======== + +This module manages apt on Debian. + +It keeps dpkg's and apt's databases as well as the keyrings for securing +package download current. + +backports.debian.org is added. + +/etc/apt/sources.list and /etc/apt/preferences are managed. More +recent Debian releases are pinned to very low values by default to +prevent accidental upgrades. + +Ubuntu support is lagging behind but not absent either. + +! Upgrade Notice ! + + * The `disable_update` parameter has been removed. The main apt class +   defaults to *not* run an `apt-get update` on every run anyway so this +   parameter seems useless. +   You can include the `apt::update` class if you want it to be run every time. + + * The `apt::upgrade_package` now doesn't automatically call an Exec['apt_updated'] +   anymore, so you would need to include `apt::update` now by hand. + + * The apt::codename parameter has been removed. In its place, the +   debian_codename fact may be overridden via an environment variable. This +   will affect all other debian_* facts, and achieve the same result. + +     FACTER_debian_codename=jessie puppet agent -t + + * If you were using custom 50unattended-upgrades.${::lsbdistcodename} in your +   site_apt, these are no longer supported. You should migrate to passing +   $blacklisted_packages to the apt::unattended_upgrades class. + + * the apt class has been moved to a paramterized class. if you were including +   this class before, after passing some variables, you will need to move to +   instantiating the class with those variables instead. For example, if you  +   had the following in your manifests: + +    $apt_debian_url = 'http://localhost:9999/debian/' +    $apt_use_next_release = true +    include apt +  +   you will need to remove the variables, and the include and instead do +   the following: + +    class { 'apt': debian_url => 'http://localhost:9999/debian/', use_next_release => true } + +   previously, you could manually set $lsbdistcodename which would enable forced +   upgrades, but because this is a top-level facter variable, and newer puppet +   versions do not let you assign variables to other namespaces, this is no +   longer possible. However, there is a way to obtain this functionality, and +   that is to pass the 'codename' parameter to the apt class, which will change +   the sources.list and preferences files to be the codename you set, allowing +   you to trigger upgrades: + +   include apt::dist_upgrade +   class { 'apt': codename => 'wheezy', notify => Exec['apt_dist-upgrade'] } + + * the apticron class has been moved to a parameterized class.  if you were +   including this class before, you will need to move to instantiating the +   class instead. For example, if you had the following in your manifests: + +    $apticron_email = 'foo@example.com' +    $apticron_notifynew = '1' +    ... any $apticron_* variables +    include apticron + +   you will need to remove the variables, and the include and instead do the +   following: + +    class { 'apt::apticron': email => 'foo@example.com', notifynew => '1' } + + * the apt::listchanges class has been moved to a paramterized class. if you +   were including this class before, after passing some variables, you will need +   to move to instantiating the class with those variables instead. For example, +   if you had the following in your manifests: + +    $apt_listchanges_email = 'foo@example.com' +    ... any $apt_listchanges_* variables +    include apt::listchanges + +   you will need to remove the variables, and the include and instead do the +   following: +  +    class { 'apt::listchanges': email => 'foo@example.com' } +    + * the apt::proxy_client class has been moved to a paramterized class. if you +   were including this class before, after passing some variables, you will need +   to move to instantiating the class with those variables instead. For example, +   if you had the following in your manifests: + +    $apt_proxy = 'http://proxy.domain' +    $apt_proxy_port = 666 +    include apt::proxy_client + +   you will need to remove the variables, and the include and instead do the +   following: + +    class { 'apt::proxy_client': proxy => 'http://proxy.domain', port => '666' } + +Requirements +============ + +This module needs: + +- the lsb-release package should be installed on the server prior to running +  puppet. otherwise, all of the $::lsb* facts will be empty during runs. +- the common module: https://gitlab.com/shared-puppet-modules-group/common + +By default, on normal hosts, this module sets the configuration option +DSelect::Clean to 'auto'. On virtual servers, the value is set by default to +'pre-auto', because virtual servers are usually more space-bound and have better +recovery mechanisms via the host: + +From apt.conf(5), 0.7.2: +     "Cache Clean mode; this value may be one of always, prompt, auto, +     pre-auto and never. always and prompt will remove all packages +     from the cache after upgrading, prompt (the default) does so +     conditionally.  auto removes only those packages which are no +     longer downloadable (replaced with a new version for +     instance). pre-auto performs this action before downloading new +     packages." + +To change the default setting for DSelect::Clean, you can create a file named +"03clean" or "03clean_vserver" in your site_apt module's files directory. You +can also define this for a specific host by creating a file in a subdirectory of +the site_apt modules' files directory that is named the same as the +host. (example: site_apt/files/some.host.com/03clean, or +site_apt/files/some.host.com/03clean_vserver) + +Classes +======= + +apt +--- + +The apt class sets up most of the documented functionality. To use functionality +that is not enabled by default, you must set one of the following parameters. + +Example usage: + + class { 'apt': use_next_release => true, debian_url => 'http://localhost:9999/debian/' } + +Class parameters: + +* use_lts + +  If this variable is set to true the CODENAME-lts sources (such as +  squeeze-lts) are added. + +  By default this is false for backward compatibility with older +  versions of this module. + +* use_volatile + +  If this variable is set to true the CODENAME-updates sources (such as +  squeeze-updates) are added. + +  By default this is false for backward compatibility with older +  versions of this module. + +* include_src + +  If this variable is set to true a deb-src source is added for every +  added binary archive source. + +  By default this is false for backward compatibility with older +  versions of this module. + +* use_next_release + +  If this variable is set to true the sources for the next Debian +  release are added. The default pinning configuration pins it to very +  low values. + +  By default this is false for backward compatibility with older +  versions of this module. + +* debian_url, security_url, backports_url, volatile_url + +  These variables allow to override the default APT mirrors respectively +  used for the standard Debian archives, the Debian security archive, +  the Debian official backports and the Debian Volatile archive. + +* ubuntu_url + +  These variables allows to override the default APT mirror used for all +  standard Ubuntu archives (including updates, security, backports). + +* repos + +  If this variable is set the default repositories list ("main contrib non-free") +  is overriden. + +* disable_update + +  Disable "apt-get update" which is normally triggered by apt::upgrade_package  +  and apt::dist_upgrade.  + +  Note that nodes can be updated once a day by using  +    APT::Periodic::Update-Package-Lists "1"; +  in i.e. /etc/apt/apt.conf.d/80_apt_update_daily. + +* custom_preferences + +  For historical reasons (Debian Lenny's version of APT did not support the use +  of the preferences.d directory for putting fragments of 'preferences'), this +  module will manage a default generic apt/preferences file with more +  recent releases pinned to very low values so that any package +  installation will not accidentally pull in packages from those suites +  unless you explicitly specify the version number. This file will be +  complemented with all of the preferences_snippet calls (see below). + +  If the default preferences template doesn't suit your needs, you can create a +  template located in your site_apt module, and set custom_preferences with the +  content (eg. custom_preferences => template('site_apt/preferences') ) + +  Setting this variable to false before including this class will force the +  apt/preferences file to be absent: + +    class { 'apt': custom_preferences => false } +   +* custom_sources_list + +  By default this module will use a basic apt/sources.list template with +  a generic Debian mirror. If you need to set more specific sources, +  e.g. changing the sections included in the source, etc. you can set +  this variable to the content that you desire to use instead. + +  For example, setting this variable will pull in the +  templates/site_apt/sources.list file: + +  class { 'apt': custom_sources_list => template('site_apt/sources.list') } + +* custom_key_dir + +  If you have different apt-key files that you want to get added to your +  apt keyring, you can set this variable to a path in your fileserver +  where individual key files can be placed. If this is set and keys +  exist there, this module will 'apt-key add' each key. + +  The debian-archive-keyring package is installed and kept current up to the +  latest revision (this includes the backports archive keyring). + +apt::apticron +------------- + +When you instantiate this class, apticron will be installed, with the following +defaults, which you are free to change: + +  $ensure_version = 'installed', +  $config = "apt/${::operatingsystem}/apticron_${::lsbdistcodename}.erb", +  $email = 'root', +  $diff_only = '1', +  $listchanges_profile = 'apticron', +  $system = false, +  $ipaddressnum = false, +  $ipaddresses = false, +  $notifyholds = '0', +  $notifynew = '0', +  $customsubject = '' + +Example usage: + + class { 'apt::apticron': email => 'foo@example.com', notifynew => '1' } + +apt::cron::download +------------------- + +This class sets up cron-apt so that it downloads upgradable packages, does not +actually do any upgrade and emails when the output changes. + +cron-apt defaults to run at 4 AM. You may want to set the +$apt_cron_hours variable before you include the class: its value will +be passed as the "hours" parameter of a cronjob. Example: + + # Run cron-apt every three hours + $apt_cron_hours = '*/3' + +Note that the default 4 AM cronjob won't be disabled. + +apt::cron::dist_upgrade +----------------------- + +This class sets up cron-apt so that it dist-upgrades the system and +emails when upgrades are performed. + +See apt::cron::download above if you need to run cron-apt more often +than once a day. + +apt::dist_upgrade +----------------- + +This class provides the Exec['apt_dist-upgrade'] resource that +dist-upgrade's the system. + +This exec is set as refreshonly so including this class does not +trigger any action per-se: other resources may notify it, other +classes may inherit from this one and add to its subscription list +using the plusignment ('+>') operator. A real-world example can be +seen in the apt::dist_upgrade::initiator source. + +apt::dist_upgrade::initiator +---------------------------- + +This class automatically dist-upgrade's the system when an initiator +file's content changes. The initiator file is copied from the first +available source amongst the following ones, in decreasing priority +order: + +- puppet:///modules/site_apt/${::fqdn}/upgrade_initiator +- puppet:///modules/site_apt/upgrade_initiator +- puppet:///modules/apt/upgrade_initiator + +This is useful when one does not want to setup a fully automated +upgrade process but still needs a way to manually trigger full +upgrades of any number of systems at scheduled times. + +Beware: a dist-upgrade is triggered the first time Puppet runs after +this class has been included. This is actually the single reason why +this class is not enabled by default. + +When this class is included the APT indexes are updated on every +Puppet run due to the author's lack of Puppet wizardry. + +apt::dselect +------------ + +This class, when included, installs dselect and switches it to expert mode to +suppress superfluous help screens. + +apt::listchanges +---------------- + +This class, when instantiated, installs apt-listchanges and configures it using +the following parameterized variables, which can be changed: + + version = 'present' + config = "apt/${::operatingsystem}/listchanges_${::lsbrelease}.erb" + frontend = 'pager' + email = 'root' + confirm = 0 + saveseen = '/var/lib/apt/listchanges.db' + which = 'both' + + Example usage: +  class { 'apt::listchanges': email => 'foo@example.com' } +  +apt::proxy_client +----------------- + +This class adds the right configuration to apt to make it fetch packages via a +proxy. The class parameters apt_proxy and apt_proxy_port need to be set: + +You can set the 'proxy' class parameter variable to the URL of the proxy that +will be used.  By default, the proxy will be queried on port 3142, but you can +change the port number by setting the 'port' class parameter. + +Example: + + class { 'apt::proxy_client': proxy => 'http://proxy.domain', port => '666' } + +apt::reboot_required_notify +--------------------------- + +This class installs a daily cronjob that checks if a package upgrade +requires the system to be rebooted; if so, cron sends a notification +email to root. + +apt::unattended_upgrades +------------------------ + +If this class is included, it will install the package 'unattended-upgrades' +and configure it to daily upgrade the system. + +The class has the following parameters that you can use to change the contents +of the configuration file. The values shown here are the default values: + + * $config_content = undef + * $config_template = 'apt/50unattended-upgrades.erb' + * $mailonlyonerror = true + * $mail_recipient = 'root' + * $blacklisted_packages = [] + +Note that using $config_content actually specifies all of the configuration +contents and thus makes the other parameters useless. + +example: + +    class { 'apt::unattended_upgrades': +      config_template      => 'site_apt/50unattended-upgrades.jessie', +      blacklisted_packages => [ +       'libc6', 'libc6-dev', 'libc6-i686', 'mysql-server', 'redmine', 'nodejs', +       'bird' +      ], +    } + +Defines +======= + +apt::apt_conf +------------- + +Creates a file in the apt/apt.conf.d directory to easily add configuration +components. One can use either the 'source' meta-parameter to specify a list of +static files to include from the puppet fileserver or the 'content' +meta-parameter to define content inline or with the help of a template. + +Example: + +  apt::apt_conf { '80download-only': +    source => 'puppet:///modules/site_apt/80download-only', +  } + +apt::preferences_snippet +------------------------ + +A way to add pinning information to files in /etc/apt/preferences.d/ + +Example: + +  apt::preferences_snippet { +    'irssi-plugin-otr': +      release => 'squeeze-backports', +      priority => 999; +  } + +  apt::preferences_snippet { +    'unstable_fallback': +      package => '*', +      release => 'unstable', +      priority => 1; +  } + +  apt::preferences_snippet { +    'ttdnsd': +      pin => 'origin deb.torproject.org', +      priority => 999; +  } + +The names of the resources will be used as the names of the files in the +preferences.d directory, so you should ensure that resource names follow the +prescribed naming scheme. + +From apt_preferences(5): +     Note that the files in the /etc/apt/preferences.d directory are parsed in +     alphanumeric ascending order and need to obey the following naming +     convention: The files have no or "pref" as filename extension and which +     only contain alphanumeric, hyphen (-), underscore (_) and period (.) +     characters - otherwise they will be silently ignored. + +apt::preseeded_package +---------------------- + +This simplifies installation of packages for which you wish to preseed the +answers to debconf. For example, if you wish to provide a preseed file for the +locales package, you would place the locales.seed file in +'site_apt/templates/${::lsbdistcodename}/locales.seeds' and then include the +following in your manifest: + +  apt::preseeded_package { locales: } + +You can also specify the content of the seed via the content parameter,  +for example: + +  apt::preseeded_package { 'apticron': +    content => 'apticron   apticron/notification   string  root@example.com', +  } + +apt::sources_list +----------------- + +Creates a file in the apt/sources.list.d directory to easily add additional apt +sources. One can use either the 'source' meta-parameter to specify a list of +static files to include from the puppet fileserver or the 'content' +meta-parameter to define content inline or with the help of a template. Ending +the resource name in '.list' is optional: it will be automatically added to the +file name if not present in the resource name. + +Example: + +  apt::sources_list { 'company_internals': +    source => [ "puppet:///modules/site_apt/${::fqdn}/company_internals.list", +                'puppet:///modules/site_apt/company_internals.list' ], +  } + +apt::key +-------- + +Deploys a secure apt OpenPGP key. This usually accompanies the +sources.list snippets above for third party repositories. For example, +you would do: + +  apt::key { 'neurodebian.gpg': +    ensure => present, +    source => 'puppet:///modules/site_apt/neurodebian.gpg', +  } + +This deploys the key in the `/etc/apt/trusted.gpg.d` directory, which +is assumed by secure apt to be binary OpenPGP keys and *not* +"ascii-armored" or "plain text" OpenPGP key material. For the latter, +use `apt::key::plain`. + +The `.gpg` extension is compulsory for `apt` to pickup the key properly. + +apt::key::plain +--------------- + +Deploys a secure apt OpenPGP key. This usually accompanies the +sources.list snippets above for third party repositories. For example, +you would do: + +  apt::key::plain { 'neurodebian.asc': +    source => 'puppet:///modules/site_apt/neurodebian.asc', +  } + +This deploys the key in the `${apt_base_dir}/keys` directory (as +opposed to `$custom_key_dir` which deploys it in `keys.d`). The reason +this exists on top of `$custom_key_dir` is to allow a more +decentralised distribution of those keys, without having all modules +throw their keys in the same directory in the manifests. + +Note that this model does *not* currently allow keys to be removed! +Use `apt::key` instead for a more practical, revokable approach, but +that needs binary keys. + +apt::upgrade_package +-------------------- + +This simplifies upgrades for DSA security announcements or point-releases. This +will ensure that the named package is upgraded to the version specified, only if +the package is installed, otherwise nothing happens. If the specified version +is 'latest' (the default), then the package is ensured to be upgraded to the +latest package revision when it becomes available. + +For example, the following upgrades the perl package to version 5.8.8-7etch1 +(if it is installed), it also upgrades the syslog-ng and perl-modules packages +to their latest (also, only if they are installed): + +upgrade_package { 'perl': +			version => '5.8.8-7etch1'; +		  'syslog-ng': +			version => latest; +		  'perl-modules': +} + +Resources +========= + +File['apt_config'] +------------------ + +Use this resource to depend on or add to a completed apt configuration + +Exec['apt_updated'] +------------------- + +After this point the APT indexes are up-to-date. +This resource is set to `refreshonly => true` so it is not run on +every puppetrun. To run this every time, you can include the `apt::update` +class. + +This resource is usually used like this to ensure current packages are +installed by Package resources: + +    include apt::update +    Package { require => Exec['apt_updated'] } + +Note that nodes can be updated once a day by using + +    APT::Periodic::Update-Package-Lists "1"; + +in i.e. /etc/apt/apt.conf.d/80_apt_update_daily. + + +Tests +===== + +To run pupept rspec tests: + +    bundle install --path vendor/bundle +    bundle exec rake spec + +Using different facter/puppet versions: + +    FACTER_GEM_VERSION=1.6.10 PUPPET_GEM_VERSION=2.7.23 bundle install --path vendor/bundle +    bundle exec rake spec + +Licensing +========= + +This puppet module is licensed under the GPL version 3 or later. Redistribution +and modification is encouraged. + +The GPL version 3 license text can be found in the "LICENSE" file accompanying +this puppet module, or at the following URL: + +http://www.gnu.org/licenses/gpl-3.0.html diff --git a/puppet/modules/apt/Rakefile b/puppet/modules/apt/Rakefile new file mode 100644 index 00000000..85326bb4 --- /dev/null +++ b/puppet/modules/apt/Rakefile @@ -0,0 +1,19 @@ +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' +PuppetLint.configuration.send('disable_80chars') +PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] + +desc "Validate manifests, templates, and ruby files" +task :validate do +  Dir['manifests/**/*.pp'].each do |manifest| +    sh "puppet parser validate --noop #{manifest}" +  end +  Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file| +    sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/ +  end +  Dir['templates/**/*.erb'].each do |template| +    sh "erb -P -x -T '-' #{template} | ruby -c" +  end +end + +task :test => [:lint, :syntax , :validate, :spec] diff --git a/puppet/modules/apt/files/02show_upgraded b/puppet/modules/apt/files/02show_upgraded new file mode 100644 index 00000000..bb127d41 --- /dev/null +++ b/puppet/modules/apt/files/02show_upgraded @@ -0,0 +1,4 @@ +// This file is managed by Puppet +// all local modifications will be overwritten + +APT::Get::Show-Upgraded true; diff --git a/puppet/modules/apt/files/03clean b/puppet/modules/apt/files/03clean new file mode 100644 index 00000000..3d20924a --- /dev/null +++ b/puppet/modules/apt/files/03clean @@ -0,0 +1,4 @@ +// This file is managed by Puppet +// all local modifications will be overwritten + +DSelect::Clean auto; diff --git a/puppet/modules/apt/files/03clean_vserver b/puppet/modules/apt/files/03clean_vserver new file mode 100644 index 00000000..6bb84e58 --- /dev/null +++ b/puppet/modules/apt/files/03clean_vserver @@ -0,0 +1,4 @@ +// This file is managed by Puppet +// all local modifications will be overwritten + +DSelect::Clean pre-auto; diff --git a/puppet/modules/apt/files/upgrade_initiator b/puppet/modules/apt/files/upgrade_initiator new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/puppet/modules/apt/files/upgrade_initiator @@ -0,0 +1 @@ + diff --git a/puppet/modules/apt/lib/facter/apt_running.rb b/puppet/modules/apt/lib/facter/apt_running.rb new file mode 100644 index 00000000..e8f2156e --- /dev/null +++ b/puppet/modules/apt/lib/facter/apt_running.rb @@ -0,0 +1,7 @@ +Facter.add("apt_running") do +  setcode do +    #Facter::Util::Resolution.exec('/usr/bin/dpkg -s mysql-server >/dev/null 2>&1 && echo true || echo false') +    Facter::Util::Resolution.exec('pgrep apt-get >/dev/null 2>&1 && echo true || echo false') +  end +end + diff --git a/puppet/modules/apt/lib/facter/debian_codename.rb b/puppet/modules/apt/lib/facter/debian_codename.rb new file mode 100644 index 00000000..254877aa --- /dev/null +++ b/puppet/modules/apt/lib/facter/debian_codename.rb @@ -0,0 +1,42 @@ +begin +  require 'facter/util/debian' +rescue LoadError +  require "#{File.dirname(__FILE__)}/util/debian" +end + +def version_to_codename(version) +  if Facter::Util::Debian::CODENAMES.has_key?(version) +    return Facter::Util::Debian::CODENAMES[version] +  else +    Facter.warn("Could not determine codename from version '#{version}'") +  end +end + +Facter.add(:debian_codename) do +  has_weight 99 +  confine :operatingsystem => 'Debian' +  setcode do +    Facter.value('lsbdistcodename') +  end +end + +Facter.add(:debian_codename) do +  has_weight 66 +  confine :operatingsystem => 'Debian' +  setcode do +    version_to_codename(Facter.value('operatingsystemmajrelease')) +  end +end + +Facter.add(:debian_codename) do +  has_weight 33 +  confine :operatingsystem => 'Debian' +  setcode do +    debian_version = File.open('/etc/debian_version', &:readline) +    if debian_version.match(/^\d+/) +      version_to_codename(debian_version.scan(/^(\d+)/)[0][0]) +    elsif debian_version.match(/^[a-z]+\/(sid|unstable)/) +      debian_version.scan(/^([a-z]+)\//)[0][0] +    end +  end +end diff --git a/puppet/modules/apt/lib/facter/debian_lts.rb b/puppet/modules/apt/lib/facter/debian_lts.rb new file mode 100644 index 00000000..f53a9eb8 --- /dev/null +++ b/puppet/modules/apt/lib/facter/debian_lts.rb @@ -0,0 +1,16 @@ +begin +  require 'facter/util/debian' +rescue LoadError +  require "#{File.dirname(__FILE__)}/util/debian" +end + +Facter.add(:debian_lts) do +  confine :operatingsystem => 'Debian' +  setcode do +    if Facter::Util::Debian::LTS.include? Facter.value('debian_codename') +      true +    else +      false +    end +  end +end diff --git a/puppet/modules/apt/lib/facter/debian_nextcodename.rb b/puppet/modules/apt/lib/facter/debian_nextcodename.rb new file mode 100644 index 00000000..c4c569b2 --- /dev/null +++ b/puppet/modules/apt/lib/facter/debian_nextcodename.rb @@ -0,0 +1,23 @@ +begin +  require 'facter/util/debian' +rescue LoadError +  require "#{File.dirname(__FILE__)}/util/debian" +end + +def debian_codename_to_next(codename) +  if codename == "sid" +    return "experimental" +  else +    codenames = Facter::Util::Debian::CODENAMES +    versions  = Facter::Util::Debian::CODENAMES.invert +    current_version = versions[codename] +    return codenames[(current_version.to_i + 1).to_s] +  end +end + +Facter.add(:debian_nextcodename) do +  confine :operatingsystem => 'Debian' +  setcode do +    debian_codename_to_next(Facter.value('debian_codename')) +  end +end diff --git a/puppet/modules/apt/lib/facter/debian_nextrelease.rb b/puppet/modules/apt/lib/facter/debian_nextrelease.rb new file mode 100644 index 00000000..2a9c4f5f --- /dev/null +++ b/puppet/modules/apt/lib/facter/debian_nextrelease.rb @@ -0,0 +1,23 @@ +def debian_release_to_next(release) +  releases = [ +    'oldoldoldstable', +    'oldoldstable', +    'oldstable', +    'stable', +    'testing', +    'unstable', +    'experimental', +  ] +  if releases.include? release +    if releases.index(release)+1 < releases.count +      return releases[releases.index(release)+1] +    end +  end +end + +Facter.add(:debian_nextrelease) do +  confine :operatingsystem => 'Debian' +  setcode do +    debian_release_to_next(Facter.value('debian_release')) +  end +end diff --git a/puppet/modules/apt/lib/facter/debian_release.rb b/puppet/modules/apt/lib/facter/debian_release.rb new file mode 100644 index 00000000..2c334ccd --- /dev/null +++ b/puppet/modules/apt/lib/facter/debian_release.rb @@ -0,0 +1,38 @@ +begin +  require 'facter/util/debian' +rescue LoadError +  require "#{File.dirname(__FILE__)}/util/debian" +end + +def debian_codename_to_release(codename) +  stable = Facter::Util::Debian::STABLE +  versions = Facter::Util::Debian::CODENAMES.invert +  release = nil +  if codename == "sid" +    release = "unstable" +  elsif versions.has_key? codename +    version = versions[codename].to_i +    if version == stable +      release = "stable" +    elsif version < stable +      release = "stable" +      for i in version..stable - 1 +        release = "old" + release +      end +    elsif version == stable + 1 +      release = "testing" +    end +  end +  if release.nil? +    Facter.warn("Could not determine release from codename #{codename}!") +  end +  return release +end + +Facter.add(:debian_release) do +  has_weight 99 +  confine :operatingsystem => 'Debian' +  setcode do +    debian_codename_to_release(Facter.value('debian_codename')) +  end +end diff --git a/puppet/modules/apt/lib/facter/ubuntu_codename.rb b/puppet/modules/apt/lib/facter/ubuntu_codename.rb new file mode 100644 index 00000000..814fd942 --- /dev/null +++ b/puppet/modules/apt/lib/facter/ubuntu_codename.rb @@ -0,0 +1,8 @@ +Facter.add(:ubuntu_codename) do +  confine :operatingsystem => 'Ubuntu' +  setcode do +    Facter.value('lsbdistcodename') +  end +end + + diff --git a/puppet/modules/apt/lib/facter/ubuntu_nextcodename.rb b/puppet/modules/apt/lib/facter/ubuntu_nextcodename.rb new file mode 100644 index 00000000..dcd1d426 --- /dev/null +++ b/puppet/modules/apt/lib/facter/ubuntu_nextcodename.rb @@ -0,0 +1,20 @@ +begin +  require 'facter/util/ubuntu' +rescue LoadError +  require "#{File.dirname(__FILE__)}/util/ubuntu" +end + +def ubuntu_codename_to_next(codename) +  codenames = Facter::Util::Ubuntu::CODENAMES +  i = codenames.index(codename) +  if i and i+1 < codenames.count +    return codenames[i+1] +  end +end + +Facter.add(:ubuntu_nextcodename) do +  confine :operatingsystem => 'Ubuntu' +  setcode do +    ubuntu_codename_to_next(Facter.value('ubuntu_codename')) +  end +end diff --git a/puppet/modules/apt/lib/facter/util/debian.rb b/puppet/modules/apt/lib/facter/util/debian.rb new file mode 100644 index 00000000..290c17b5 --- /dev/null +++ b/puppet/modules/apt/lib/facter/util/debian.rb @@ -0,0 +1,18 @@ +module Facter +  module Util +    module Debian +      STABLE = 8 +      CODENAMES = { +        "5" => "lenny", +        "6" => "squeeze", +        "7" => "wheezy", +        "8" => "jessie", +        "9" => "stretch", +        "10" => "buster", +      } +      LTS = [ +        "squeeze", +      ] +    end +  end +end diff --git a/puppet/modules/apt/lib/facter/util/ubuntu.rb b/puppet/modules/apt/lib/facter/util/ubuntu.rb new file mode 100644 index 00000000..52c15e80 --- /dev/null +++ b/puppet/modules/apt/lib/facter/util/ubuntu.rb @@ -0,0 +1,21 @@ +module Facter +  module Util +    module Ubuntu +      CODENAMES = [ +        "lucid", +        "maverick", +        "natty", +        "oneiric", +        "precise", +        "quantal", +        "raring", +        "saucy", +        "trusty", +        "utopic", +        "vivid", +        "wily", +        "xenial" +      ] +    end +  end +end diff --git a/puppet/modules/apt/manifests/apt_conf.pp b/puppet/modules/apt/manifests/apt_conf.pp new file mode 100644 index 00000000..949f6157 --- /dev/null +++ b/puppet/modules/apt/manifests/apt_conf.pp @@ -0,0 +1,45 @@ +define apt::apt_conf( +  $ensure = 'present', +  $source = '', +  $content = undef, +  $refresh_apt = true ) +{ + +  if $source == '' and $content == undef { +    fail("One of \$source or \$content must be specified for apt_conf ${name}") +  } + +  if $source != '' and $content != undef { +    fail("Only one of \$source or \$content must specified for apt_conf ${name}") +  } + +  include apt::dot_d_directories + +  # One would expect the 'file' resource on sources.list.d to trigger an +  # apt-get update when files are added or modified in the directory, but it +  # apparently doesn't. +  file { "/etc/apt/apt.conf.d/${name}": +    ensure => $ensure, +    owner  => root, +    group  => 0, +    mode   => '0644', +  } + +  if $source { +    File["/etc/apt/apt.conf.d/${name}"] { +      source => $source, +    } +  } +  else { +    File["/etc/apt/apt.conf.d/${name}"] { +      content => $content, +    } +  } + +  if $refresh_apt { +    File["/etc/apt/apt.conf.d/${name}"] { +      notify => Exec['apt_updated'], +    } +  } + +} diff --git a/puppet/modules/apt/manifests/apticron.pp b/puppet/modules/apt/manifests/apticron.pp new file mode 100644 index 00000000..9c94f9c9 --- /dev/null +++ b/puppet/modules/apt/manifests/apticron.pp @@ -0,0 +1,24 @@ +class apt::apticron( +  $ensure_version = 'installed', +  $config = "apt/${::operatingsystem}/apticron_${::debian_codename}.erb", +  $email = 'root', +  $diff_only = '1', +  $listchanges_profile = 'apticron', +  $system = false, +  $ipaddressnum = false, +  $ipaddresses = false, +  $notifyholds = '0', +  $notifynew = '0', +  $customsubject = '' +) { + +  package { 'apticron': ensure => $ensure_version } + +  file { '/etc/apticron/apticron.conf': +    content => template($apt::apticron::config), +    owner   => root, +    group   => root, +    mode    => '0644', +    require => Package['apticron']; +  } +} diff --git a/puppet/modules/apt/manifests/cron/base.pp b/puppet/modules/apt/manifests/cron/base.pp new file mode 100644 index 00000000..39fc3061 --- /dev/null +++ b/puppet/modules/apt/manifests/cron/base.pp @@ -0,0 +1,20 @@ +class apt::cron::base { + +  package { 'cron-apt': ensure => installed } + +  case $apt_cron_hours { +    '': {} +    default: { +      # cron-apt defaults to run every night at 4 o'clock +      # so we try not to run at the same time. +      cron { 'apt_cron_every_N_hours': +        command => 'test -x /usr/sbin/cron-apt && /usr/sbin/cron-apt', +        user    => root, +        hour    => "${apt_cron_hours}", +        minute  => 10, +        require => Package['cron-apt'], +      } +    } +  } + +} diff --git a/puppet/modules/apt/manifests/cron/dist_upgrade.pp b/puppet/modules/apt/manifests/cron/dist_upgrade.pp new file mode 100644 index 00000000..74403bb7 --- /dev/null +++ b/puppet/modules/apt/manifests/cron/dist_upgrade.pp @@ -0,0 +1,29 @@ +class apt::cron::dist_upgrade inherits apt::cron::base { + +  $action = "autoclean -y +dist-upgrade -y -o APT::Get::Show-Upgraded=true -o 'DPkg::Options::=--force-confold' +" + +  file { '/etc/cron-apt/action.d/3-download': +    ensure => absent, +  } + +  package { 'apt-listbugs': ensure => absent } + +  file { '/etc/cron-apt/action.d/4-dist-upgrade': +    content => $action, +    owner   => root, +    group   => 0, +    mode    => '0644', +    require => Package[cron-apt]; +  } + +  file { '/etc/cron-apt/config.d/MAILON': +    content => "MAILON=upgrade\n", +    owner   => root, +    group   => 0, +    mode    => '0644', +    require => Package[cron-apt]; +  } + +} diff --git a/puppet/modules/apt/manifests/cron/download.pp b/puppet/modules/apt/manifests/cron/download.pp new file mode 100644 index 00000000..4a19fec1 --- /dev/null +++ b/puppet/modules/apt/manifests/cron/download.pp @@ -0,0 +1,27 @@ +class apt::cron::download inherits apt::cron::base { + +  $action = "autoclean -y +dist-upgrade -d -y -o APT::Get::Show-Upgraded=true +" + +  file { '/etc/cron-apt/action.d/4-dist-upgrade': +    ensure => absent, +  } + +  file { '/etc/cron-apt/action.d/3-download': +    content => $action, +    require => Package[cron-apt], +    owner   => root, +    group   => 0, +    mode    => '0644'; +  } + +  file { '/etc/cron-apt/config.d/MAILON': +    content => "MAILON=changes\n", +    require => Package[cron-apt], +    owner   => root, +    group   => 0, +    mode    => '0644'; +  } + +} diff --git a/puppet/modules/apt/manifests/dist_upgrade.pp b/puppet/modules/apt/manifests/dist_upgrade.pp new file mode 100644 index 00000000..19c031e0 --- /dev/null +++ b/puppet/modules/apt/manifests/dist_upgrade.pp @@ -0,0 +1,9 @@ +class apt::dist_upgrade { + +  exec { 'apt_dist-upgrade': +    command     => '/usr/bin/apt-get -q -y -o \'DPkg::Options::=--force-confold\' dist-upgrade', +    refreshonly => true, +    before      => Exec['apt_updated'] +  } + +} diff --git a/puppet/modules/apt/manifests/dist_upgrade/initiator.pp b/puppet/modules/apt/manifests/dist_upgrade/initiator.pp new file mode 100644 index 00000000..d2389883 --- /dev/null +++ b/puppet/modules/apt/manifests/dist_upgrade/initiator.pp @@ -0,0 +1,23 @@ +class apt::dist_upgrade::initiator inherits apt::dist_upgrade { + +  $initiator = 'upgrade_initiator' +  $initiator_abs = "${apt::apt_base_dir}/${initiator}" + +  file { 'apt_upgrade_initiator': +    mode     => '0644', +    owner    => root, +    group    => 0, +    path     => $initiator_abs, +    checksum => md5, +    source   => [ +                  "puppet:///modules/site_apt/${::fqdn}/${initiator}", +                  "puppet:///modules/site_apt/${initiator}", +                  "puppet:///modules/apt/${initiator}", +                ], +  } + +  Exec['apt_dist-upgrade'] { +    subscribe +> File['apt_upgrade_initiator'], +  } + +} diff --git a/puppet/modules/apt/manifests/dot_d_directories.pp b/puppet/modules/apt/manifests/dot_d_directories.pp new file mode 100644 index 00000000..0ace8630 --- /dev/null +++ b/puppet/modules/apt/manifests/dot_d_directories.pp @@ -0,0 +1,15 @@ +class apt::dot_d_directories { + +  # watch .d directories and ensure they are present +  file { +    '/etc/apt/apt.conf.d': +      ensure   => directory, +      checksum => mtime, +      notify   => Exec['apt_updated']; +    '/etc/apt/sources.list.d': +      ensure   => directory, +      checksum => mtime, +      notify   => Exec['apt_updated']; +  } + +} diff --git a/puppet/modules/apt/manifests/dselect.pp b/puppet/modules/apt/manifests/dselect.pp new file mode 100644 index 00000000..2b99a43d --- /dev/null +++ b/puppet/modules/apt/manifests/dselect.pp @@ -0,0 +1,11 @@ +# manage dselect, like +# suppressing the annoying help texts +class apt::dselect { + +  file_line { 'dselect_expert': +    path => '/etc/dpkg/dselect.cfg', +    line => 'expert', +  } + +  package { 'dselect': ensure => installed } +} diff --git a/puppet/modules/apt/manifests/init.pp b/puppet/modules/apt/manifests/init.pp new file mode 100644 index 00000000..4c44af2a --- /dev/null +++ b/puppet/modules/apt/manifests/init.pp @@ -0,0 +1,150 @@ +# apt.pp - common components and defaults for handling apt +# Copyright (C) 2008 Micah Anerson <micah@riseup.net> +# Copyright (C) 2007 David Schmitt <david@schmitt.edv-bus.at> +# See LICENSE for the full license granted to you. + +class apt( +  $use_lts = $apt::params::use_lts, +  $use_volatile = $apt::params::use_volatile, +  $use_backports = $apt::params::use_backports, +  $include_src = $apt::params::include_src, +  $use_next_release = $apt::params::use_next_release, +  $debian_url = $apt::params::debian_url, +  $security_url = $apt::params::security_url, +  $backports_url = $apt::params::backports_url, +  $lts_url = $apt::params::lts_url, +  $volatile_url = $apt::params::volatile_url, +  $ubuntu_url = $apt::params::ubuntu_url, +  $repos = $apt::params::repos, +  $custom_preferences = $apt::params::custom_preferences, +  $custom_sources_list = '', +  $custom_key_dir = $apt::params::custom_key_dir +) inherits apt::params { +  case $::operatingsystem { +    'debian': { +      $real_repos = $repos ? { +        'auto'  => 'main contrib non-free', +        default => $repos, +      } +    } +    'ubuntu': { +      $real_repos = $repos ? { +        'auto'  => 'main restricted universe multiverse', +        default => $repos, +      } +    } +  } + +  package { 'apt': +    ensure  => installed, +    require => undef, +  } + +  $sources_content = $custom_sources_list ? { +    ''      => template( "apt/${::operatingsystem}/sources.list.erb"), +    default => $custom_sources_list +  } +  file { +    # include main and security +    # additional sources should be included via the apt::sources_list define +    '/etc/apt/sources.list': +      content => $sources_content, +      notify  => Exec['apt_updated'], +      owner   => root, +      group   => 0, +      mode    => '0644'; +  } + +  apt_conf { '02show_upgraded': +    source => [ "puppet:///modules/site_apt/${::fqdn}/02show_upgraded", +                'puppet:///modules/site_apt/02show_upgraded', +                'puppet:///modules/apt/02show_upgraded' ] +  } + +  if ( $::virtual == 'vserver' ) { +    apt_conf { '03clean_vserver': +      source => [ "puppet:///modules/site_apt/${::fqdn}/03clean_vserver", +                  'puppet:///modules/site_apt/03clean_vserver', +                  'puppet:///modules/apt/03clean_vserver' ], +      alias => '03clean'; +    } +  } +  else { +    apt_conf { '03clean': +      source => [ "puppet:///modules/site_apt/${::fqdn}/03clean", +                  'puppet:///modules/site_apt/03clean', +                  'puppet:///modules/apt/03clean' ] +    } +  } + +  case $custom_preferences { +    false: { +      include apt::preferences::absent +    } +    default: { +      # When squeeze becomes the stable branch, transform this file's header +      # into a preferences.d file +      include apt::preferences +    } +  } + +  include apt::dot_d_directories + +  ## This package should really always be current +  package { 'debian-archive-keyring': ensure => latest } + +  # backports uses the normal archive key now +  package { 'debian-backports-keyring': ensure => absent } + +  if ($use_backports and !($::debian_release in ['testing', 'unstable', 'experimental'])) { +    apt::sources_list { +      'backports': +        content => "deb $backports_url ${::debian_codename}-backports ${apt::real_repos}", +    } +    if $include_src { +      apt::sources_list { +        'backports-src': +          content => "deb-src $backports_url ${::debian_codename}-backports ${apt::real_repos}", +      } +    } +  } + +  include common::moduledir +  common::module_dir { 'apt': } +  $apt_base_dir = "${common::moduledir::module_dir_path}/apt" + +  if $custom_key_dir { +    file { "${apt_base_dir}/keys.d": +      source  => $custom_key_dir, +      recurse => true, +      owner   => root, +      group   => root, +      mode    => '0755', +    } +    exec { 'custom_keys': +      command     => "find ${apt_base_dir}/keys.d -type f -exec apt-key add '{}' \\;", +      subscribe   => File["${apt_base_dir}/keys.d"], +      refreshonly => true, +      notify      => Exec[refresh_apt] +    } +    if $custom_preferences != false { +      Exec['custom_keys'] { +        before => File['apt_config'] +      } +    } +  } + +  # workaround for preseeded_package component +  file { [ '/var/cache', '/var/cache/local', '/var/cache/local/preseeding' ]: ensure => directory } + +  exec { 'update_apt': +    command     => '/usr/bin/apt-get update', +    require     => [ +      File['/etc/apt/apt.conf.d', '/etc/apt/preferences' ], +      File['/etc/apt/sources.list'] ], +    refreshonly => true, +    # Another Semaphor for all packages to reference +    alias       => [ 'apt_updated', 'refresh_apt'] +  } + +} diff --git a/puppet/modules/apt/manifests/key.pp b/puppet/modules/apt/manifests/key.pp new file mode 100644 index 00000000..cb70ec6a --- /dev/null +++ b/puppet/modules/apt/manifests/key.pp @@ -0,0 +1,13 @@ +define apt::key ($source, $ensure = 'present') { +  validate_re( +    $name, '\.gpg$', +    'An apt::key resource name must have the .gpg extension', +  ) + +  file { +    "/etc/apt/trusted.gpg.d/${name}": +      ensure => $ensure, +      source => $source, +      notify => Exec['apt_updated'], +  } +} diff --git a/puppet/modules/apt/manifests/key/plain.pp b/puppet/modules/apt/manifests/key/plain.pp new file mode 100644 index 00000000..dff8b51b --- /dev/null +++ b/puppet/modules/apt/manifests/key/plain.pp @@ -0,0 +1,13 @@ +define apt::key::plain ($source) { +  file { +    "${apt::apt_base_dir}/keys/${name}": +      source  => $source; +    "${apt::apt_base_dir}/keys": +      ensure  => directory; +  } +  exec { "apt-key add '${apt::apt_base_dir}/keys/${name}'": +    subscribe   => File["${apt::apt_base_dir}/keys/${name}"], +    refreshonly => true, +    notify      => Exec['apt_updated'], +  } +} diff --git a/puppet/modules/apt/manifests/listchanges.pp b/puppet/modules/apt/manifests/listchanges.pp new file mode 100644 index 00000000..e64bb1b7 --- /dev/null +++ b/puppet/modules/apt/manifests/listchanges.pp @@ -0,0 +1,19 @@ +class apt::listchanges( +  $ensure_version = 'installed', +  $config = "apt/${::operatingsystem}/listchanges_${::debian_codename}.erb", +  $frontend = 'mail', +  $email = 'root', +  $confirm = '0', +  $saveseen = '/var/lib/apt/listchanges.db', +  $which = 'both' +){ +  package { 'apt-listchanges': ensure => $ensure_version } + +  file { '/etc/apt/listchanges.conf': +    content => template($apt::listchanges::config), +    owner   => root, +    group   => root, +    mode    => '0644', +    require => Package['apt-listchanges']; +  } +} diff --git a/puppet/modules/apt/manifests/params.pp b/puppet/modules/apt/manifests/params.pp new file mode 100644 index 00000000..28af06eb --- /dev/null +++ b/puppet/modules/apt/manifests/params.pp @@ -0,0 +1,22 @@ +class apt::params () { +  $use_lts = false +  $use_volatile = false +  $use_backports = true +  $include_src = false +  $use_next_release = false +  $debian_url = 'http://httpredir.debian.org/debian/' +  $security_url = 'http://security.debian.org/' +  $ubuntu_url = 'http://archive.ubuntu.com/ubuntu' +  $backports_url = $::debian_codename ? { +    'squeeze'  => 'http://backports.debian.org/debian-backports/', +    default => $::operatingsystem ? { +      'Ubuntu' => $ubuntu_url, +      default  => $debian_url, +    } +  } +  $lts_url = $debian_url +  $volatile_url = 'http://volatile.debian.org/debian-volatile/' +  $repos = 'auto' +  $custom_preferences = '' +  $custom_key_dir = false +} diff --git a/puppet/modules/apt/manifests/preferences.pp b/puppet/modules/apt/manifests/preferences.pp new file mode 100644 index 00000000..6982ca05 --- /dev/null +++ b/puppet/modules/apt/manifests/preferences.pp @@ -0,0 +1,20 @@ +class apt::preferences { + +  $pref_contents = $apt::custom_preferences ? { +    ''      => $::operatingsystem ? { +      'debian' => template("apt/${::operatingsystem}/preferences_${::debian_codename}.erb"), +      'ubuntu' => template("apt/${::operatingsystem}/preferences_${::ubuntu_codename}.erb"), +    }, +    default => $apt::custom_preferences +  } + +  file { '/etc/apt/preferences': +    ensure  => present, +    alias   => 'apt_config', +    # only update together +    content => $pref_contents, +    require => File['/etc/apt/sources.list'], +    owner   => root, group => 0, mode => '0644'; +  } + +} diff --git a/puppet/modules/apt/manifests/preferences/absent.pp b/puppet/modules/apt/manifests/preferences/absent.pp new file mode 100644 index 00000000..f32e0307 --- /dev/null +++ b/puppet/modules/apt/manifests/preferences/absent.pp @@ -0,0 +1,7 @@ +class apt::preferences::absent { + +  file { '/etc/apt/preferences': +    ensure => absent, +    alias  => 'apt_config', +  } +} diff --git a/puppet/modules/apt/manifests/preferences_snippet.pp b/puppet/modules/apt/manifests/preferences_snippet.pp new file mode 100644 index 00000000..b7dba0d8 --- /dev/null +++ b/puppet/modules/apt/manifests/preferences_snippet.pp @@ -0,0 +1,59 @@ +define apt::preferences_snippet ( +  $priority = undef, +  $package = false, +  $ensure = 'present', +  $source = '', +  $release = '', +  $pin = '' +) { + +  $real_package = $package ? { +    false   => $name, +    default => $package, +  } + +  if $ensure == 'present' { +    if $apt::custom_preferences == false { +      fail('Trying to define a preferences_snippet with $custom_preferences set to false.') +    } + +    if $priority == undef { +      fail('apt::preferences_snippet requires the \'priority\' argument to be set') +    } + +    if !$pin and !$release { +      fail('apt::preferences_snippet requires one of the \'pin\' or \'release\' argument to be set') +    } +    if $pin and $release { +      fail('apt::preferences_snippet requires either a \'pin\' or \'release\' argument, not both') +    } +  } + +  file { "/etc/apt/preferences.d/${name}": +    ensure => $ensure, +    owner  => root, group => 0, mode => '0644', +    before => Exec['apt_updated']; +  } + +  case $source { +    '': { +      case $release { +        '': { +          File["/etc/apt/preferences.d/${name}"]{ +            content => template('apt/preferences_snippet.erb') +          } +        } +        default: { +          File["/etc/apt/preferences.d/${name}"]{ +            content => template('apt/preferences_snippet_release.erb') +          } +        } +      } +    } +    default: { +      File["/etc/apt/preferences.d/${name}"]{ +        source => $source +      } +    } +  } +} diff --git a/puppet/modules/apt/manifests/preseeded_package.pp b/puppet/modules/apt/manifests/preseeded_package.pp new file mode 100644 index 00000000..3ef06879 --- /dev/null +++ b/puppet/modules/apt/manifests/preseeded_package.pp @@ -0,0 +1,21 @@ +define apt::preseeded_package ( +  $ensure = 'installed', +  $content = '' +) { +  $seedfile = "/var/cache/local/preseeding/${name}.seeds" +  $real_content = $content ? { +    ''      => template ( "site_apt/${::debian_codename}/${name}.seeds" ), +    default => $content +  } + +  file { $seedfile: +    content => $real_content, +    mode    => '0600', owner => root, group => root, +  } + +  package { $name: +    ensure       => $ensure, +    responsefile => $seedfile, +    require      => File[$seedfile], +  } +} diff --git a/puppet/modules/apt/manifests/proxy_client.pp b/puppet/modules/apt/manifests/proxy_client.pp new file mode 100644 index 00000000..9ba79f23 --- /dev/null +++ b/puppet/modules/apt/manifests/proxy_client.pp @@ -0,0 +1,9 @@ +class apt::proxy_client( +  $proxy = 'http://localhost', +  $port = '3142', +){ + +  apt_conf { '20proxy': +    content => template('apt/20proxy.erb'), +  } +} diff --git a/puppet/modules/apt/manifests/reboot_required_notify.pp b/puppet/modules/apt/manifests/reboot_required_notify.pp new file mode 100644 index 00000000..722e8a5e --- /dev/null +++ b/puppet/modules/apt/manifests/reboot_required_notify.pp @@ -0,0 +1,21 @@ +class apt::reboot_required_notify { + +  # This package installs the script that created /var/run/reboot-required*. +  # This script (/usr/share/update-notifier/notify-reboot-required) is +  # triggered e.g. by kernel packages. +  package { 'update-notifier-common': +    ensure => installed, +  } + +  # cron-apt defaults to run every night at 4 o'clock +  # plus some random time <1h. +  # so we check if a reboot is required a bit later. +  cron { 'apt_reboot_required_notify': +    command => 'if [ -f /var/run/reboot-required ]; then echo "Reboot required\n" ; cat /var/run/reboot-required.pkgs ; fi', +    user    => root, +    hour    => 5, +    minute  => 20, +    require => Package['update-notifier-common'], +  } + +} diff --git a/puppet/modules/apt/manifests/sources_list.pp b/puppet/modules/apt/manifests/sources_list.pp new file mode 100644 index 00000000..0ee068d1 --- /dev/null +++ b/puppet/modules/apt/manifests/sources_list.pp @@ -0,0 +1,40 @@ +define apt::sources_list ( +  $ensure = 'present', +  $source = '', +  $content = undef +) { + +  if $ensure == 'present' { +    if $source == '' and $content == undef { +      fail("One of \$source or \$content must be specified for apt_sources_snippet ${name}") +    } +    if $source != '' and $content != undef { +      fail("Only one of \$source or \$content must specified for apt_sources_snippet ${name}") +    } +  } + +  include apt::dot_d_directories + +  $realname = regsubst($name, '\.list$', '') + +  # One would expect the 'file' resource on sources.list.d to trigger an +  # apt-get update when files are added or modified in the directory, but it +  # apparently doesn't. +  file { "/etc/apt/sources.list.d/${realname}.list": +    ensure => $ensure, +    owner  => root, group => 0, mode => '0644', +    notify => Exec['apt_updated'], +  } + +  if $source { +    File["/etc/apt/sources.list.d/${realname}.list"] { +      source => $source, +    } +  } +  else { +    File["/etc/apt/sources.list.d/${realname}.list"] { +      content => $content, +    } +  } +} + diff --git a/puppet/modules/apt/manifests/unattended_upgrades.pp b/puppet/modules/apt/manifests/unattended_upgrades.pp new file mode 100644 index 00000000..52d75425 --- /dev/null +++ b/puppet/modules/apt/manifests/unattended_upgrades.pp @@ -0,0 +1,34 @@ +class apt::unattended_upgrades ( +  $config_content = undef, +  $config_template = 'apt/50unattended-upgrades.erb', +  $mailonlyonerror = true, +  $mail_recipient = 'root', +  $blacklisted_packages = [], +  $ensure_version = present +) { + +  package { 'unattended-upgrades': +    ensure  => $ensure_version +  } + +  # For some reason, this directory is sometimes absent, which causes +  # unattended-upgrades to crash. +  file { '/var/log/unattended-upgrades': +    ensure  => directory, +    owner   => 'root', +    group   => 0, +    mode    => '0755', +    require => Package['unattended-upgrades'], +  } + +  $file_content = $config_content ? { +    undef   => template($config_template), +    default => $config_content +  } + +  apt_conf { '50unattended-upgrades': +    content     => $file_content, +    require     => Package['unattended-upgrades'], +    refresh_apt => false +  } +} diff --git a/puppet/modules/apt/manifests/update.pp b/puppet/modules/apt/manifests/update.pp new file mode 100644 index 00000000..dde83200 --- /dev/null +++ b/puppet/modules/apt/manifests/update.pp @@ -0,0 +1,7 @@ +class apt::update inherits ::apt { + +  Exec['update_apt'] { +    refreshonly => false +  } + +} diff --git a/puppet/modules/apt/manifests/upgrade_package.pp b/puppet/modules/apt/manifests/upgrade_package.pp new file mode 100644 index 00000000..30572c96 --- /dev/null +++ b/puppet/modules/apt/manifests/upgrade_package.pp @@ -0,0 +1,31 @@ +define apt::upgrade_package ( +  $version = '' +) { + +  $version_suffix = $version ? { +    ''       => '', +    'latest' => '', +    default  => "=${version}", +  } + +  if !defined(Package['apt-show-versions']) { +    package { 'apt-show-versions': +      ensure  => installed, +      require => undef, +    } +  } + +  if !defined(Package['dctrl-tools']) { +    package { 'dctrl-tools': +      ensure  => installed, +      require => undef, +    } +  } + +  exec { "apt-get -q -y -o 'DPkg::Options::=--force-confold' install ${name}${version_suffix}": +    onlyif  => [ "grep-status -F Status installed -a -P $name -q", "apt-show-versions -u $name | grep -q upgradeable" ], +    require => Package['apt-show-versions', 'dctrl-tools'], +    before  => Exec['apt_updated'] +  } + +} diff --git a/puppet/modules/apt/spec/spec_helper.rb b/puppet/modules/apt/spec/spec_helper.rb new file mode 100644 index 00000000..21d1a988 --- /dev/null +++ b/puppet/modules/apt/spec/spec_helper.rb @@ -0,0 +1,12 @@ +# https://puppetlabs.com/blog/testing-modules-in-the-puppet-forge +require 'rspec-puppet' +require 'mocha/api' + +RSpec.configure do |c| + +  c.module_path = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')) +  c.color = true + +  #Puppet.features.stubs(:root? => true) + +end diff --git a/puppet/modules/apt/spec/unit/custom_facts_spec.rb b/puppet/modules/apt/spec/unit/custom_facts_spec.rb new file mode 100644 index 00000000..9a28d92e --- /dev/null +++ b/puppet/modules/apt/spec/unit/custom_facts_spec.rb @@ -0,0 +1,86 @@ +require "spec_helper" + +describe "Facter::Util::Fact" do +  before { +    Facter.clear +  } + +  describe 'custom facts' do + +    context 'Debian 7' do +      before do +        Facter.fact(:operatingsystem).stubs(:value).returns("Debian") +        Facter.fact(:operatingsystemrelease).stubs(:value).returns("7.8") +        Facter.fact(:lsbdistcodename).stubs(:value).returns("wheezy") +      end + +      it "debian_release = oldstable" do +        expect(Facter.fact(:debian_release).value).to eq('oldstable') +      end + +      it "debian_codename = wheezy" do +        expect(Facter.fact(:debian_codename).value).to eq('wheezy') +      end + +      it "debian_nextcodename = jessie" do +        expect(Facter.fact(:debian_nextcodename).value).to eq('jessie') +      end + +      it "debian_nextrelease = stable" do +        expect(Facter.fact(:debian_nextrelease).value).to eq('stable') +      end +    end + +    context 'Debian 8' do +      before do +        Facter.fact(:operatingsystem).stubs(:value).returns("Debian") +        Facter.fact(:operatingsystemrelease).stubs(:value).returns("8.0") +        Facter.fact(:lsbdistcodename).stubs(:value).returns("jessie") +      end + +      it "debian_release = stable" do +        expect(Facter.fact(:debian_release).value).to eq('stable') +      end + +      it "debian_codename = jessie" do +        expect(Facter.fact(:debian_codename).value).to eq('jessie') +      end + +      it "debian_nextcodename = stretch" do +        expect(Facter.fact(:debian_nextcodename).value).to eq('stretch') +      end + +      it "debian_nextrelease = testing" do +        expect(Facter.fact(:debian_nextrelease).value).to eq('testing') +      end +    end + +    context 'Ubuntu 15.10' do +      before do +        Facter.fact(:operatingsystem).stubs(:value).returns("Ubuntu") +        Facter.fact(:operatingsystemrelease).stubs(:value).returns("15.10") +        Facter.fact(:lsbdistcodename).stubs(:value).returns("wily") +      end + +      it "ubuntu_codename = wily" do +        expect(Facter.fact(:ubuntu_codename).value).to eq('wily') +      end + +      it "ubuntu_nextcodename = xenial" do +        expect(Facter.fact(:ubuntu_nextcodename).value).to eq('xenial') +      end +    end +  end + +  describe "Test 'apt_running' fact" do +    it "should return true when apt-get is running" do +      Facter::Util::Resolution.stubs(:exec).with("pgrep apt-get >/dev/null 2>&1 && echo true || echo false").returns("true") +      expect(Facter.fact(:apt_running).value).to eq('true') +    end +    it "should return false when apt-get is not running" do +      Facter::Util::Resolution.stubs(:exec).with("pgrep apt-get >/dev/null 2>&1 && echo true || echo false").returns("false") +      expect(Facter.fact(:apt_running).value).to eq('false') +    end +  end + +end diff --git a/puppet/modules/apt/templates/20proxy.erb b/puppet/modules/apt/templates/20proxy.erb new file mode 100644 index 00000000..520e7b1b --- /dev/null +++ b/puppet/modules/apt/templates/20proxy.erb @@ -0,0 +1,5 @@ +// This file is managed by Puppet +// all local modifications will be overwritten + +Acquire::http { Proxy "<%= @proxy %>:<%= @port %>"; }; +Acquire::HTTP::Proxy::bugs.debian.org "DIRECT"; diff --git a/puppet/modules/apt/templates/50unattended-upgrades.erb b/puppet/modules/apt/templates/50unattended-upgrades.erb new file mode 100644 index 00000000..7c65d102 --- /dev/null +++ b/puppet/modules/apt/templates/50unattended-upgrades.erb @@ -0,0 +1,38 @@ +// this file is managed by puppet ! + +<% if scope.lookupvar('::operatingsystem') == 'Ubuntu' -%> +Unattended-Upgrade::Allowed-Origins { +  "${distro_id}:${distro_codename}-security"; +  "${distro_id}:${distro_codename}-updates"; +  "${distro_id}:${distro_codename}-backports"; +<% elsif scope.lookupvar('::operatingsystem') == 'Debian' and scope.lookupvar('::debian_codename') == 'squeeze' -%> +Unattended-Upgrade::Allowed-Origins { +  "${distro_id}:<%= scope.lookupvar('::debian_release') %>"; +  "${distro_id}:squeeze-lts"; +<% elsif scope.lookupvar('::operatingsystem') == 'Debian' and scope.lookupvar('::debian_codename') == 'wheezy' -%> +Unattended-Upgrade::Origins-Pattern { +  "origin=Debian,archive=<%= scope.lookupvar('::debian_release') %>,label=Debian-Security"; +  "origin=Debian,archive=${distro_codename}-lts"; +<% else -%> +Unattended-Upgrade::Origins-Pattern { +  "origin=Debian,codename=${distro_codename},label=Debian"; +  "origin=Debian,codename=${distro_codename},label=Debian-Security"; +<% end -%> +}; + +<% if not @blacklisted_packages.empty?  -%> +Unattended-Upgrade::Package-Blacklist { +<% @blacklisted_packages.each do |pkg| -%> +  "<%= pkg %>"; +<% end -%> +}; +<% end -%> + +APT::Periodic::Update-Package-Lists "1"; +APT::Periodic::Download-Upgradeable-Packages "1"; +APT::Periodic::Unattended-Upgrade "1"; + +Unattended-Upgrade::Mail "<%= @mail_recipient -%>"; +<% if @mailonlyonerror -%> +Unattended-Upgrade::MailOnlyOnError "true"; +<% end -%> diff --git a/puppet/modules/apt/templates/Debian/apticron_jessie.erb b/puppet/modules/apt/templates/Debian/apticron_jessie.erb new file mode 120000 index 00000000..a9a3a6fd --- /dev/null +++ b/puppet/modules/apt/templates/Debian/apticron_jessie.erb @@ -0,0 +1 @@ +apticron_wheezy.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Debian/apticron_lenny.erb b/puppet/modules/apt/templates/Debian/apticron_lenny.erb new file mode 100644 index 00000000..86b09977 --- /dev/null +++ b/puppet/modules/apt/templates/Debian/apticron_lenny.erb @@ -0,0 +1,50 @@ +# apticron.conf +# +# set EMAIL to a list of addresses which will be notified of impending updates +# +EMAIL="<%= scope.lookupvar('apt::apticron::email') %>" + +# +# Set DIFF_ONLY to "1" to only output the difference of the current run +# compared to the last run (ie. only new upgrades since the last run). If there +# are no differences, no output/email will be generated. By default, apticron +# will output everything that needs to be upgraded. +# +DIFF_ONLY="<%= scope.lookupvar('apt::apticron::diff_only') %>" + +# +# Set LISTCHANGES_PROFILE if you would like apticron to invoke apt-listchanges +# with the --profile option. You should add a corresponding profile to +# /etc/apt/listchanges.conf +# +LISTCHANGES_PROFILE="<%= scope.lookupvar('apt::apticron::listchanges_profile') %>" + +# +# Set SYSTEM if you would like apticron to use something other than the output +# of "hostname -f" for the system name in the mails it generates +# +# SYSTEM="foobar.example.com" +<% unless (v=scope.lookupvar('apt::apticron::system')).to_s == "false" -%> +SYSTEM="<%= v %>" +<% end -%> + +# +# Set IPADDRESSNUM if you would like to configure the maximal number of IP +# addresses apticron displays. The default is to display 1 address of each +# family type (inet, inet6), if available. +# +# IPADDRESSNUM="1" +<% unless (v=scope.lookupvar('apt::apticron::ipaddressnum')).to_s == "false" -%> +IPADDRESSNUM="<%= v %>" +<% end -%> + +# +# Set IPADDRESSES to a whitespace seperated list of reachable addresses for +# this system. By default, apticron will try to work these out using the +# "ip" command +# +# IPADDRESSES="192.0.2.1 2001:db8:1:2:3::1" +<% unless (v=scope.lookupvar('apt::apticron::ipaddresses')).to_s == "false" -%> +IPADDRESSES="<%= v %>" +<% end -%> + diff --git a/puppet/modules/apt/templates/Debian/apticron_sid.erb b/puppet/modules/apt/templates/Debian/apticron_sid.erb new file mode 120000 index 00000000..a9a3a6fd --- /dev/null +++ b/puppet/modules/apt/templates/Debian/apticron_sid.erb @@ -0,0 +1 @@ +apticron_wheezy.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Debian/apticron_squeeze.erb b/puppet/modules/apt/templates/Debian/apticron_squeeze.erb new file mode 100644 index 00000000..05b7c9b8 --- /dev/null +++ b/puppet/modules/apt/templates/Debian/apticron_squeeze.erb @@ -0,0 +1,82 @@ +# apticron.conf +# +# set EMAIL to a space separated list of addresses which will be notified of +# impending updates +# +EMAIL="<%= scope.lookupvar('apt::apticron::email') %>" + + +# +# Set DIFF_ONLY to "1" to only output the difference of the current run +# compared to the last run (ie. only new upgrades since the last run). If there +# are no differences, no output/email will be generated. By default, apticron +# will output everything that needs to be upgraded. +# +DIFF_ONLY="<%= scope.lookupvar('apt::apticron::diff_only') %>" + +# +# Set LISTCHANGES_PROFILE if you would like apticron to invoke apt-listchanges +# with the --profile option. You should add a corresponding profile to +# /etc/apt/listchanges.conf +# +LISTCHANGES_PROFILE="<%= scope.lookupvar('apt::apticron::listchanges_profile') %>" + +# +# Set SYSTEM if you would like apticron to use something other than the output +# of "hostname -f" for the system name in the mails it generates +# +# SYSTEM="foobar.example.com" +<% unless (v=scope.lookupvar('apt::apticron::system')).to_s == "false" -%> +SYSTEM="<%= v %>" +<% end -%> + + +# +# Set IPADDRESSNUM if you would like to configure the maximal number of IP +# addresses apticron displays. The default is to display 1 address of each +# family type (inet, inet6), if available. +# +# IPADDRESSNUM="1" +<% unless (v=scope.lookupvar('apt::apticron::ipaddressnum')).to_s == "false" -%> +IPADDRESSNUM="<%= v %>" +<% end -%> + + +# +# Set IPADDRESSES to a whitespace separated list of reachable addresses for +# this system. By default, apticron will try to work these out using the +# "ip" command +# +# IPADDRESSES="192.0.2.1 2001:db8:1:2:3::1" +<% unless (v=scope.lookupvar('apt::apticron::ipaddresses')).to_s == "false" -%> +IPADDRESSES="<%= v %>" +<% end -%> + + +# +# Set NOTIFY_HOLDS="0" if you don't want to be notified about new versions of +# packages on hold in your system. The default behavior is downloading and +# listing them as any other package. +# +# NOTIFY_HOLDS="0" +NOTIFY_HOLDS="<%= scope.lookupvar('apt::apticron::notifyholds') %>" + +# +# Set NOTIFY_NEW="0" if you don't want to be notified about packages which +# are not installed in your system. Yes, it's possible! There are some issues +# related to systems which have mixed stable/unstable sources. In these cases +# apt-get will consider for example that packages with "Priority: +# required"/"Essential: yes" in unstable but not in stable should be installed, +# so they will be listed in dist-upgrade output. Please take a look at +# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=531002#44 +# +# NOTIFY_NEW="0" +NOTIFY_NEW="<%= scope.lookupvar('apt::apticron::notifynew') %>" + +# +# Set CUSTOM_SUBJECT if you want to replace the default subject used in +# the notification e-mails. This may help filtering/sorting client-side e-mail. +# +# CUSTOM_SUBJECT="" +CUSTOM_SUBJECT="<%= scope.lookupvar('apt::apticron::customsubject') %>" + diff --git a/puppet/modules/apt/templates/Debian/apticron_wheezy.erb b/puppet/modules/apt/templates/Debian/apticron_wheezy.erb new file mode 100644 index 00000000..655854e6 --- /dev/null +++ b/puppet/modules/apt/templates/Debian/apticron_wheezy.erb @@ -0,0 +1,80 @@ +# apticron.conf +# +# set EMAIL to a space separated list of addresses which will be notified of +# impending updates +# +EMAIL="<%= scope.lookupvar('apt::apticron::email') %>" + +# +# Set DIFF_ONLY to "1" to only output the difference of the current run +# compared to the last run (ie. only new upgrades since the last run). If there +# are no differences, no output/email will be generated. By default, apticron +# will output everything that needs to be upgraded. +# +DIFF_ONLY="<%= scope.lookupvar('apt::apticron::diff_only') %>" + +# +# Set LISTCHANGES_PROFILE if you would like apticron to invoke apt-listchanges +# with the --profile option. You should add a corresponding profile to +# /etc/apt/listchanges.conf +# +LISTCHANGES_PROFILE="<%= scope.lookupvar('apt::apticron::listchanges_profile') %>" + +# +# Set SYSTEM if you would like apticron to use something other than the output +# of "hostname -f" for the system name in the mails it generates +# +# SYSTEM="foobar.example.com" +<% unless (v=scope.lookupvar('apt::apticron::system')).to_s == "false" -%> +SYSTEM="<%= v %>" +<% end -%> + +# +# Set IPADDRESSNUM if you would like to configure the maximal number of IP +# addresses apticron displays. The default is to display 1 address of each +# family type (inet, inet6), if available. +# +# IPADDRESSNUM="1" +<% unless (v=scope.lookupvar('apt::apticron::ipaddressnum')).to_s == "false" -%> +IPADDRESSNUM="<%= v %>" +<% end -%> + +# +# Set IPADDRESSES to a whitespace separated list of reachable addresses for +# this system. By default, apticron will try to work these out using the +# "ip" command +# +# IPADDRESSES="192.0.2.1 2001:db8:1:2:3::1" +<% unless (v=scope.lookupvar('apt::apticron::ipaddresses')).to_s == "false" -%> +IPADDRESSES=<%= v %>" +<% end -%> + +# +# Set NOTIFY_HOLDS="0" if you don't want to be notified about new versions of +# packages on hold in your system. The default behavior is downloading and +# listing them as any other package. +# +# NOTIFY_HOLDS="0" +NOTIFY_HOLDS="<%= scope.lookupvar('apt::apticron::notifyholds') %>" + +# +# Set NOTIFY_NEW="0" if you don't want to be notified about packages which +# are not installed in your system. Yes, it's possible! There are some issues +# related to systems which have mixed stable/unstable sources. In these cases +# apt-get will consider for example that packages with "Priority: +# required"/"Essential: yes" in unstable but not in stable should be installed, +# so they will be listed in dist-upgrade output. Please take a look at +# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=531002#44 +# +# NOTIFY_NEW="0" +NOTIFY_NEW="<%= scope.lookupvar('apt::apticron::notifynew') %>" + + +# +# Set CUSTOM_SUBJECT if you want to replace the default subject used in +# the notification e-mails. This may help filtering/sorting client-side e-mail. +# If you want to use internal vars please use single quotes here. Ex: +# ='[apticron] :  package update(s)' +# +# CUSTOM_SUBJECT="" +CUSTOM_SUBJECT="<%= scope.lookupvar('apt::apticron::customsubject') %>" diff --git a/puppet/modules/apt/templates/Debian/listchanges_jessie.erb b/puppet/modules/apt/templates/Debian/listchanges_jessie.erb new file mode 120000 index 00000000..74ab496d --- /dev/null +++ b/puppet/modules/apt/templates/Debian/listchanges_jessie.erb @@ -0,0 +1 @@ +listchanges_lenny.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Debian/listchanges_lenny.erb b/puppet/modules/apt/templates/Debian/listchanges_lenny.erb new file mode 100644 index 00000000..1025dd0e --- /dev/null +++ b/puppet/modules/apt/templates/Debian/listchanges_lenny.erb @@ -0,0 +1,7 @@ +[apt] +frontend=<%= scope.lookupvar('apt::listchanges::frontend') %> +email_address=<%= scope.lookupvar('apt::listchanges::email') %> +confirm=<%= scope.lookupvar('apt::listchanges::confirm') %> +save_seen=<%= scope.lookupvar('apt::listchanges::saveseen') %> +which=<%= scope.lookupvar('apt::listchanges::which') %> + diff --git a/puppet/modules/apt/templates/Debian/listchanges_sid.erb b/puppet/modules/apt/templates/Debian/listchanges_sid.erb new file mode 120000 index 00000000..74ab496d --- /dev/null +++ b/puppet/modules/apt/templates/Debian/listchanges_sid.erb @@ -0,0 +1 @@ +listchanges_lenny.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Debian/listchanges_squeeze.erb b/puppet/modules/apt/templates/Debian/listchanges_squeeze.erb new file mode 120000 index 00000000..74ab496d --- /dev/null +++ b/puppet/modules/apt/templates/Debian/listchanges_squeeze.erb @@ -0,0 +1 @@ +listchanges_lenny.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Debian/listchanges_wheezy.erb b/puppet/modules/apt/templates/Debian/listchanges_wheezy.erb new file mode 120000 index 00000000..74ab496d --- /dev/null +++ b/puppet/modules/apt/templates/Debian/listchanges_wheezy.erb @@ -0,0 +1 @@ +listchanges_lenny.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Debian/preferences_jessie.erb b/puppet/modules/apt/templates/Debian/preferences_jessie.erb new file mode 100644 index 00000000..0888abe5 --- /dev/null +++ b/puppet/modules/apt/templates/Debian/preferences_jessie.erb @@ -0,0 +1,14 @@ +Explanation: Debian <%= codename=scope.lookupvar('::debian_codename') %> +Package: * +Pin: release o=Debian,n=<%= codename %> +Pin-Priority: 990 + +Explanation: Debian sid +Package: * +Pin: release o=Debian,n=sid +Pin-Priority: 1 + +Explanation: Debian fallback +Package: * +Pin: release o=Debian +Pin-Priority: -10 diff --git a/puppet/modules/apt/templates/Debian/preferences_lenny.erb b/puppet/modules/apt/templates/Debian/preferences_lenny.erb new file mode 100644 index 00000000..65001687 --- /dev/null +++ b/puppet/modules/apt/templates/Debian/preferences_lenny.erb @@ -0,0 +1,25 @@ +Explanation: Debian <%= codename=scope.lookupvar('::debian_codename') %> +Package: * +Pin: release o=Debian,a=<%= scope.lookupvar('::debian_release') %>,v=5* +Pin-Priority: 990 + +Explanation: Debian backports +Package: * +Pin: origin backports.debian.org +Pin-Priority: 200 + +Explanation: Debian <%= next_release=scope.lookupvar('::debian_nextrelease') %> +Package: * +Pin: release o=Debian,a=<%= next_release %> +Pin-Priority: 2 + +Explanation: Debian sid +Package: * +Pin: release o=Debian,a=unstable +Pin-Priority: 1 + +Explanation: Debian fallback +Package: * +Pin: release o=Debian +Pin-Priority: -10 + diff --git a/puppet/modules/apt/templates/Debian/preferences_sid.erb b/puppet/modules/apt/templates/Debian/preferences_sid.erb new file mode 100644 index 00000000..eb185543 --- /dev/null +++ b/puppet/modules/apt/templates/Debian/preferences_sid.erb @@ -0,0 +1,10 @@ +Explanation: Debian sid +Package: * +Pin: release o=Debian,n=sid +Pin-Priority: 990 + +Explanation: Debian fallback +Package: * +Pin: release o=Debian +Pin-Priority: -10 + diff --git a/puppet/modules/apt/templates/Debian/preferences_squeeze.erb b/puppet/modules/apt/templates/Debian/preferences_squeeze.erb new file mode 100644 index 00000000..885edc73 --- /dev/null +++ b/puppet/modules/apt/templates/Debian/preferences_squeeze.erb @@ -0,0 +1,30 @@ +Explanation: Debian <%= codename=scope.lookupvar('::debian_codename') %> +Package: * +Pin: release o=Debian,n=<%= codename %> +Pin-Priority: 990 + +Explanation: Debian <%= codename %>-updates +Package: * +Pin: release o=Debian,n=<%= codename %>-updates +Pin-Priority: 990 + +Explanation: Debian <%= codename %>-lts +Package: * +Pin: release o=Debian,n=<%= codename %>-lts +Pin-Priority: 990 + +Explanation: Debian <%= next_codename=scope.lookupvar('::debian_nextcodename') %> +Package: * +Pin: release o=Debian,n=<%= next_codename %> +Pin-Priority: 2 + +Explanation: Debian sid +Package: * +Pin: release o=Debian,n=sid +Pin-Priority: 1 + +Explanation: Debian fallback +Package: * +Pin: release o=Debian +Pin-Priority: -10 + diff --git a/puppet/modules/apt/templates/Debian/preferences_wheezy.erb b/puppet/modules/apt/templates/Debian/preferences_wheezy.erb new file mode 100644 index 00000000..106108d5 --- /dev/null +++ b/puppet/modules/apt/templates/Debian/preferences_wheezy.erb @@ -0,0 +1,20 @@ +Explanation: Debian <%= codename=scope.lookupvar('::debian_codename') %> +Package: * +Pin: release o=Debian,n=<%= codename %> +Pin-Priority: 990 + +Explanation: Debian <%= codename %>-updates +Package: * +Pin: release o=Debian,n=<%= codename %>-updates +Pin-Priority: 990 + +Explanation: Debian sid +Package: * +Pin: release o=Debian,n=sid +Pin-Priority: 1 + +Explanation: Debian fallback +Package: * +Pin: release o=Debian +Pin-Priority: -10 + diff --git a/puppet/modules/apt/templates/Debian/sources.list.erb b/puppet/modules/apt/templates/Debian/sources.list.erb new file mode 100644 index 00000000..44eea538 --- /dev/null +++ b/puppet/modules/apt/templates/Debian/sources.list.erb @@ -0,0 +1,76 @@ +# This file is managed by puppet +# all local modifications will be overwritten + +### Debian current: <%= codename=scope.lookupvar('::debian_codename') %> + +# basic +deb <%= debian_url=scope.lookupvar('apt::debian_url') %> <%= codename %> <%= lrepos=scope.lookupvar('apt::real_repos') %> +<% if include_src=scope.lookupvar('apt::include_src')  -%> +deb-src <%= debian_url %> <%= codename %> <%= lrepos %> +<% end -%> + +# security +<% if ((release=scope.lookupvar('::debian_release')) == "stable" || release == "oldstable") -%> +deb <%= security_url=scope.lookupvar('apt::security_url') %> <%= codename %>/updates <%= lrepos %> +<%   if include_src -%> +deb-src <%= security_url %> <%= codename %>/updates <%= lrepos %> +<% end -%> +<% else -%> +# There is no security support for <%= release %> +<% end -%> + +<% if use_volatile=scope.lookupvar('apt::use_volatile') -%> +# volatile +<%   if (release == "testing" || release == "unstable" || release == "experimental") -%> +# There is no volatile archive for <%= release %> +<%   else -%> +deb <%= debian_url %> <%= codename %>-updates <%= lrepos %> +<%     if include_src -%> +deb-src <%= debian_url %> <%= codename %>-updates <%= lrepos %> +<%     end +     end +   end -%> + +<% if use_lts=scope.lookupvar('apt::use_lts') -%> +# LTS +<% if release_lts=scope.lookupvar('::debian_lts') == "false" -%> +# There is no LTS archive for <%= release %> +<% else -%> +deb <%= debian_url %> <%= codename %>-lts <%= lrepos %> +<% if include_src -%> +deb-src <%= debian_url %> <%= codename %>-lts <%= lrepos %> +<% end -%> +<% end -%> +<% end -%> + +<% if next_release=scope.lookupvar('apt::use_next_release') -%> +### Debian next: <%= next_release=scope.lookupvar('::debian_nextrelease') ; next_codename=scope.lookupvar('::debian_nextcodename') %> + +# basic +deb <%= debian_url %> <%= next_codename %> <%= lrepos %> +<%   if include_src -%> +deb-src <%= debian_url %> <%= next_codename %> <%= lrepos %> +<%   end -%> + +# security +<%   if (next_release == "unstable" || next_release == "experimental") -%> +# There is no security support for <%= next_release %> +<%   else -%> +deb <%= security_url %> <%= next_codename %>/updates <%= lrepos %> +<%     if include_src then -%> +deb-src <%= security_url %> <%= next_codename %>/updates <%= lrepos %> +<%     end +     end -%> + +<%   if use_volatile -%> +# volatile +<%     if (next_release == "testing" || next_release == "unstable" || next_release == "experimental") -%> +# There is no volatile archive for <%= next_release %> +<%     else -%> +deb <%= debian_url %> <%= next_codename %>-updates <%= lrepos %> +<%       if include_src -%> +deb-src <%= debian_url %> <%= next_codename %>-updates <%= lrepos %> +<%       end +       end +     end +   end -%> diff --git a/puppet/modules/apt/templates/Ubuntu/preferences_lucid.erb b/puppet/modules/apt/templates/Ubuntu/preferences_lucid.erb new file mode 120000 index 00000000..3debe4fc --- /dev/null +++ b/puppet/modules/apt/templates/Ubuntu/preferences_lucid.erb @@ -0,0 +1 @@ +preferences_maverick.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Ubuntu/preferences_maverick.erb b/puppet/modules/apt/templates/Ubuntu/preferences_maverick.erb new file mode 100644 index 00000000..8e5481d3 --- /dev/null +++ b/puppet/modules/apt/templates/Ubuntu/preferences_maverick.erb @@ -0,0 +1,30 @@ +Explanation: Ubuntu <%= codename=scope.lookupvar('::ubuntu_codename') %> security +Package: * +Pin: release o=Ubuntu,a=<%= codename %>-security +Pin-Priority: 990 + +Explanation: Ubuntu <%= codename %> updates +Package: * +Pin: release o=Ubuntu,a=<%= codename %>-updates +Pin-Priority: 980 + +Explanation: Ubuntu <%= codename %> +Package: * +Pin: release o=Ubuntu,a=<%= codename %> +Pin-Priority: 970 + +Explanation: Ubuntu backports +Package: * +Pin: release a=<%= codename %>-backports +Pin-Priority: 200 + +Explanation: Ubuntu <%= next_release=scope.lookupvar('::ubuntu_nextcodename') %> +Package: * +Pin: release o=Ubuntu,a=<%= next_release %> +Pin-Priority: 2 + +Explanation: Ubuntu fallback +Package: * +Pin: release o=Ubuntu +Pin-Priority: -10 + diff --git a/puppet/modules/apt/templates/Ubuntu/preferences_oneiric.erb b/puppet/modules/apt/templates/Ubuntu/preferences_oneiric.erb new file mode 120000 index 00000000..3debe4fc --- /dev/null +++ b/puppet/modules/apt/templates/Ubuntu/preferences_oneiric.erb @@ -0,0 +1 @@ +preferences_maverick.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Ubuntu/preferences_precise.erb b/puppet/modules/apt/templates/Ubuntu/preferences_precise.erb new file mode 120000 index 00000000..3debe4fc --- /dev/null +++ b/puppet/modules/apt/templates/Ubuntu/preferences_precise.erb @@ -0,0 +1 @@ +preferences_maverick.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Ubuntu/preferences_utopic.erb b/puppet/modules/apt/templates/Ubuntu/preferences_utopic.erb new file mode 120000 index 00000000..3debe4fc --- /dev/null +++ b/puppet/modules/apt/templates/Ubuntu/preferences_utopic.erb @@ -0,0 +1 @@ +preferences_maverick.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Ubuntu/preferences_vivid.erb b/puppet/modules/apt/templates/Ubuntu/preferences_vivid.erb new file mode 120000 index 00000000..3debe4fc --- /dev/null +++ b/puppet/modules/apt/templates/Ubuntu/preferences_vivid.erb @@ -0,0 +1 @@ +preferences_maverick.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Ubuntu/preferences_wily.erb b/puppet/modules/apt/templates/Ubuntu/preferences_wily.erb new file mode 120000 index 00000000..3debe4fc --- /dev/null +++ b/puppet/modules/apt/templates/Ubuntu/preferences_wily.erb @@ -0,0 +1 @@ +preferences_maverick.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Ubuntu/preferences_xenial.erb b/puppet/modules/apt/templates/Ubuntu/preferences_xenial.erb new file mode 120000 index 00000000..3debe4fc --- /dev/null +++ b/puppet/modules/apt/templates/Ubuntu/preferences_xenial.erb @@ -0,0 +1 @@ +preferences_maverick.erb
\ No newline at end of file diff --git a/puppet/modules/apt/templates/Ubuntu/sources.list.erb b/puppet/modules/apt/templates/Ubuntu/sources.list.erb new file mode 100644 index 00000000..e6d2f643 --- /dev/null +++ b/puppet/modules/apt/templates/Ubuntu/sources.list.erb @@ -0,0 +1,22 @@ +# This file is managed by puppet +# all local modifications will be overwritten + +# basic <%= codename=scope.lookupvar('::ubuntu_codename') %> +deb <%= ubuntu_url=scope.lookupvar('apt::ubuntu_url') %> <%= codename %> <%= lrepos=scope.lookupvar('apt::real_repos') %> +<% if include_src=scope.lookupvar('apt::include_src') -%> +deb-src <%= ubuntu_url %> <%= codename %> <%= lrepos %> +<% end -%> + +<% if use_volatile=scope.lookupvar('apt::use_volatile') -%> +# updates +deb <%= ubuntu_url %> <%= codename %>-updates <%= lrepos %> +<%   if include_src -%> +deb-src <%= ubuntu_url %> <%= codename %>-updates <%= lrepos %> +<%   end +   end -%> + +# security suppport +deb <%= ubuntu_url %> <%= codename %>-security <%= lrepos %> +<% if include_src -%> +deb-src <%= ubuntu_url %> <%= codename %>-security <%= lrepos %> +<% end -%> diff --git a/puppet/modules/apt/templates/preferences_snippet.erb b/puppet/modules/apt/templates/preferences_snippet.erb new file mode 100644 index 00000000..903e73d6 --- /dev/null +++ b/puppet/modules/apt/templates/preferences_snippet.erb @@ -0,0 +1,4 @@ +Package: <%= @real_package %> +Pin: <%= @pin %> +Pin-Priority: <%= @priority %> + diff --git a/puppet/modules/apt/templates/preferences_snippet_release.erb b/puppet/modules/apt/templates/preferences_snippet_release.erb new file mode 100644 index 00000000..b95d3f81 --- /dev/null +++ b/puppet/modules/apt/templates/preferences_snippet_release.erb @@ -0,0 +1,4 @@ +Package: <%= @real_package %> +Pin: release a=<%= @release %> +Pin-Priority: <%= @priority %> + diff --git a/puppet/modules/bundler/.gitignore b/puppet/modules/bundler/.gitignore new file mode 100644 index 00000000..1377554e --- /dev/null +++ b/puppet/modules/bundler/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/puppet/modules/bundler/LICENSE b/puppet/modules/bundler/LICENSE new file mode 100644 index 00000000..9cef3784 --- /dev/null +++ b/puppet/modules/bundler/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2012 Evan Stachowiak + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +    http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/puppet/modules/bundler/README.md b/puppet/modules/bundler/README.md new file mode 100644 index 00000000..2abb1cfc --- /dev/null +++ b/puppet/modules/bundler/README.md @@ -0,0 +1,63 @@ +puppet-bundler - Bundler gem manager for Ruby +========================================== + +This puppet module will install bundler and set config  +variables. + +This module supports Ubuntu 10.04 and Debian + +Installation +------------ + +1. Copy this directory to your puppet master module path $(git clone +https://github.com/evanstachowiak/puppet-bundler bundler) + +2. Apply the `bundler` class to any nodes you want bundler installed on: + +  class { 'bundler::install': } + +   By default this will install bundler with RVM, if you wish to use another +   method, you can pass any puppet package provider to the class as +   'install_method', or just use 'package' if you wish the puppet parser to +   automatically chose the best method for your platform. + +  Examples: class { 'bundler::install': install_method => 'fink' } +            class { 'bundler::install': install_method => 'gem' } +            class { 'bundler::install': install_method => 'package' } + +3. Set whatever config variables are necessary:  +   bundler::config { 'linecache19': +    user        => ubuntu, +    config_flag => "--with-ruby-include=/usr/local/rvm/src/ruby-1.9.2-p290", +    app_dir     => your_app_dir, +  } + + +Contributing +------------ + +- fork on github (https://github.com/evanstachowiak/puppet-bundler) +- send a pull request + +Author +------ +Evan Stachowiak (https://github.com/evanstachowiak) + +LICENSE +------- + +    Author:: Evan Stachowiak +    Copyright:: Copyright (c) 2012 Evan Stachowiak +    License:: Apache License, Version 2.0 + +    Licensed under the Apache License, Version 2.0 (the "License"); +    you may not use this file except in compliance with the License. +    You may obtain a copy of the License at + +        http://www.apache.org/licenses/LICENSE-2.0 + +    Unless required by applicable law or agreed to in writing, software +    distributed under the License is distributed on an "AS IS" BASIS, +    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +    See the License for the specific language governing permissions and +    limitations under the License. diff --git a/puppet/modules/bundler/manifests/config.pp b/puppet/modules/bundler/manifests/config.pp new file mode 100644 index 00000000..5937a228 --- /dev/null +++ b/puppet/modules/bundler/manifests/config.pp @@ -0,0 +1,74 @@ +# Define bundler::config +# +# All config settings for candiapp class +# +# == Parameters +# +#   [*user*] +#     App directory owner +#   [*config_flag*] +#     config flag for specific gem compile settings +#   [*app_dir*] +#     App directory where Gemfile is located +#   [*home_dir_base_path*] +#     Home directory of the specified user +#   [*use_rvm*] +#      Sets whether rvm is used. Defaults to true +#   [*rvm_bin*] +#     RVM install location. Defaults to /usr/local/rvm/bin/rvm +#   [*rvm_gem_path*] +#     RVM gem directory. Defaults to /usr/local/rvm/gems +#   [*rvm_gemset*] +#     RVM gemset to use. Defaults to global. +#   [*ruby_version*] +#     Ruby version for RVM purposes. +#   [*bundler_path*] +#     Bundler install directory +# +# == Examples +# +# +# == Requires: +# +#   class { bundler::install: } +# +define bundler::config ( +  $user, +  $config_flag, +  $app_dir, +  $home_dir_base_path = $bundler::params::home_dir_base_path, +  $use_rvm            = $bundler::params::use_rvm, +  $rvm_bin            = $bundler::params::rvm_bin, +  $rvm_gem_path       = $bundler::params::rvm_gem_path, +  $rvm_gemset         = $bundler::params::rvm_gemset, +  $ruby_version       = $bundler::ruby_version, +  $bundler_path       = $bundler::params::bundler_path +) { + +  Class['bundler::install'] -> Bundler::Config[$name] + +  if $user == 'root' { +    $home_dir = '/root' +  } +  else { +    $home_dir = "${home_dir_base_path}/${user}" +  } + +  # Must use $bundler_path_real, otherwise cannot reassign variable error is thrown +  if $use_rvm == 'true' { +    $bundler_path_rvm = "${rvm_gem_path}/${ruby_version}@${rvm_gemset}/bin" +    $bundler_bin = "${rvm_bin} ${ruby_version} exec ${bundler_path_rvm}/bundle" +  } +  else { +    $bundler_bin = "${bundler_path}/bundle" +  } + +  # Bundler doesn't respect uid. Use /bin/su to override this behavior for users +  # other than root. +  exec { "bundler_config_${name}": +    cwd       => $app_dir, +    command   => "/bin/su -c '${bundler_bin} config build.${name} ${config_flag} --gemfile=${app_dir}/Gemfile' ${user}", +    unless    => "/bin/grep -i \"BUNDLE_BUILD__${name}: ${config_flag}\" ${home_dir}/.bundle/config", +  } + +} diff --git a/puppet/modules/bundler/manifests/install.pp b/puppet/modules/bundler/manifests/install.pp new file mode 100644 index 00000000..1524de31 --- /dev/null +++ b/puppet/modules/bundler/manifests/install.pp @@ -0,0 +1,64 @@ +# Class bundler::install +# +# Installs bundler Ruby gem manager +# +# == Parameters +# +#   [*install_method*] +#     How to install bundler, 'rvm' is the default +#   [*ruby_version*] +#     Ruby version that bundler will use. +# +# == Examples +# +# +# == Requires: +# +#   If use_rvm = 'true': +#   include rvm +# +class bundler::install ( +  $ruby_version    = undef, +  $ensure          = 'present', +  $install_method  = 'rvm', +  $use_rvm         = '', +  ) inherits bundler::params { + +  # deprecation warning +  if $use_rvm != '' { +    warning('$use_rvm is deprecated, please use $install_method instead') +  } + +  if ( $install_method == undef ) or ( $install_method == 'package' ) { +    $provider_method = undef +  } +  else { +    # backwards compatibility +    if $use_rvm == false { +      $provider_method = gem +    } +    else { +      $provider_method = $bundler::params::install_method +    } +  } + +  if $provider_method == 'rvm' { +    if $ruby_version == undef { +      fail('When using rvm, you must pass a ruby_version') +    } +    else { +      #Install bundler with correct RVM +      rvm_gem { 'bundler': +        ensure       => $ensure, +        ruby_version => $ruby_version, +      } +    } +  } +  else { +    package { 'bundler': +      ensure   => $ensure, +      provider => $provider_method, +    } +  } + +} diff --git a/puppet/modules/bundler/manifests/params.pp b/puppet/modules/bundler/manifests/params.pp new file mode 100644 index 00000000..53ca86e4 --- /dev/null +++ b/puppet/modules/bundler/manifests/params.pp @@ -0,0 +1,31 @@ +# Class bundler::params +# +# All config settings for candiapp class +# +# == Parameters +# +# +# +# == Examples +# +# +# == Requires: +# +class bundler::params { + +  case $::operatingsystem { +    ubuntu, debian: { +      $user               = 'root' +      $home_dir_base_path = '/home' +      $install_method     = 'rvm' +      $rvm_bin            = '/usr/local/rvm/bin/rvm' +      $rvm_gem_path       = '/usr/local/rvm/gems' +      $rvm_gemset         = 'global' +      $bundler_path       = '/usr/bin' +    } +    default: { +      fail("Unsupported platform: ${::operatingsystem}") +    } +  } + +} diff --git a/puppet/modules/clamav/files/01-leap.conf b/puppet/modules/clamav/files/01-leap.conf new file mode 100644 index 00000000..a7e49d17 --- /dev/null +++ b/puppet/modules/clamav/files/01-leap.conf @@ -0,0 +1,58 @@ +# If running clamd in "LocalSocket" mode (*NOT* in TCP/IP mode), and +# either "SOcket Cat" (socat) or the "IO::Socket::UNIX" perl module +# are installed on the system, and you want to report whether clamd +# is running or not, uncomment the "clamd_socket" variable below (you +# will be warned if neither socat nor IO::Socket::UNIX are found, but +# the script will still run).  You will also need to set the correct +# path to your clamd socket file (if unsure of the path, check the +# "LocalSocket" setting in your clamd.conf file for socket location). +clamd_socket="/run/clamav/clamd.ctl" + +# If you would like to attempt to restart ClamD if detected not running, +# uncomment the next 2 lines.  Confirm the path to the "clamd_lock" file +# (usually can be found in the clamd init script) and also enter the clamd +# start command for your particular distro for the "start_clamd" variable +# (the sample start command shown below should work for most linux distros). +# NOTE: these 2 variables are dependant on the "clamd_socket" variable +# shown above - if not enabled, then the following 2 variables will be +# ignored, whether enabled or not. +clamd_lock="/run/clamav/clamd.pid" +start_clamd="clamdscan --reload" + +ss_dbs=" +   junk.ndb +   phish.ndb +   rogue.hdb +   sanesecurity.ftm +   scam.ndb +   sigwhitelist.ign2 +   spamattach.hdb +   spamimg.hdb +   winnow.attachments.hdb +   winnow_bad_cw.hdb +   winnow_extended_malware.hdb +   winnow_malware.hdb +   winnow_malware_links.ndb +   malwarehash.hsb +   doppelstern.hdb +   bofhland_cracked_URL.ndb +   bofhland_malware_attach.hdb +   bofhland_malware_URL.ndb +   bofhland_phishing_URL.ndb +   crdfam.clamav.hdb +   phishtank.ndb +   porcupine.ndb +   spear.ndb +   spearl.ndb +" + +# ======================== +# SecuriteInfo Database(s) +# ======================== +# Add or remove database file names between quote marks as needed.  To +# disable any SecuriteInfo database downloads, remove the appropriate +# lines below.  To disable all SecuriteInfo database file downloads, +# comment all of the following lines. +si_dbs="" + +mbl_dbs=""
\ No newline at end of file diff --git a/puppet/modules/clamav/files/clamav-daemon_default b/puppet/modules/clamav/files/clamav-daemon_default new file mode 100644 index 00000000..b4cd6a4f --- /dev/null +++ b/puppet/modules/clamav/files/clamav-daemon_default @@ -0,0 +1,8 @@ +# This is a file designed only t0 set special environment variables +# eg TMP or TMPDIR.  It is sourced from a shell script, so anything +# put in here must be in variable=value format, suitable for sourcing +# from a shell script. +# Examples: +# export TMPDIR=/dev/shm +export TMP=/var/tmp +export TMPDIR=/var/tmp diff --git a/puppet/modules/clamav/files/clamav-milter_default b/puppet/modules/clamav/files/clamav-milter_default new file mode 100644 index 00000000..5e33e822 --- /dev/null +++ b/puppet/modules/clamav/files/clamav-milter_default @@ -0,0 +1,14 @@ +# +# clamav-milter init options +# + +## SOCKET_RWGROUP +# by default, the socket created by the milter has permissions +# clamav:clamav:755. SOCKET_RWGROUP changes the group and changes the +# permissions to 775 to give read-write access to that group. +# +# If you are using postfix to speak to the milter, you have to give permission +# to the postfix group to write +# +SOCKET_RWGROUP=postfix +export TMPDIR=/var/tmp diff --git a/puppet/modules/clamav/manifests/daemon.pp b/puppet/modules/clamav/manifests/daemon.pp new file mode 100644 index 00000000..2e13a8fb --- /dev/null +++ b/puppet/modules/clamav/manifests/daemon.pp @@ -0,0 +1,91 @@ +# deploy clamav daemon +class clamav::daemon { + +  $domain_hash           = hiera('domain') +  $domain                = $domain_hash['full_suffix'] + +  package { [ 'clamav-daemon', 'arj' ]: +    ensure => installed; +  } + +  service { +    'clamav-daemon': +      ensure     => running, +      name       => clamav-daemon, +      pattern    => '/usr/sbin/clamd', +      enable     => true, +      hasrestart => true, +      subscribe  => File['/etc/default/clamav-daemon'], +      require    => Package['clamav-daemon']; +  } + +  file { +    '/var/run/clamav': +      ensure  => directory, +      mode    => '0750', +      owner   => clamav, +      group   => postfix, +      require => [Package['postfix'], Package['clamav-daemon']]; + +    '/var/lib/clamav': +      mode    => '0755', +      owner   => clamav, +      group   => clamav, +      require => Package['clamav-daemon']; + +    '/etc/default/clamav-daemon': +      source => 'puppet:///modules/clamav/clamav-daemon_default', +      mode   => '0644', +      owner  => root, +      group  => root; + +    # this file contains additional domains that we want the clamav +    # phishing process to look for (our domain) +    '/var/lib/clamav/local.pdb': +      content => template('clamav/local.pdb.erb'), +      mode    => '0644', +      owner   => clamav, +      group   => clamav, +      require => Package['clamav-daemon']; +  } + +  file_line { +    'clamav_daemon_tmp': +      path    => '/etc/clamav/clamd.conf', +      line    => 'TemporaryDirectory /var/tmp', +      require => Package['clamav-daemon'], +      notify  => Service['clamav-daemon']; + +    'enable_phishscanurls': +      path    => '/etc/clamav/clamd.conf', +      match   => 'PhishingScanURLs no', +      line    => 'PhishingScanURLs yes', +      require => Package['clamav-daemon'], +      notify  => Service['clamav-daemon']; + +    'clamav_LogSyslog_true': +      path    => '/etc/clamav/clamd.conf', +      match   => '^LogSyslog false', +      line    => 'LogSyslog true', +      require => Package['clamav-daemon'], +      notify  => Service['clamav-daemon']; + +    'clamav_MaxThreads': +      path    => '/etc/clamav/clamd.conf', +      match   => 'MaxThreads 20', +      line    => 'MaxThreads 100', +      require => Package['clamav-daemon'], +      notify  => Service['clamav-daemon']; +  } + +  # remove LogFile line +  file_line { +    'clamav_LogFile': +      path    => '/etc/clamav/clamd.conf', +      match   => '^LogFile .*', +      line    => '', +      require => Package['clamav-daemon'], +      notify  => Service['clamav-daemon']; +  } + +} diff --git a/puppet/modules/clamav/manifests/freshclam.pp b/puppet/modules/clamav/manifests/freshclam.pp new file mode 100644 index 00000000..80c822a4 --- /dev/null +++ b/puppet/modules/clamav/manifests/freshclam.pp @@ -0,0 +1,23 @@ +class clamav::freshclam { + +  package { 'clamav-freshclam': ensure => installed } + +  service { +    'freshclam': +      ensure     => running, +      enable     => true, +      name       => clamav-freshclam, +      pattern    => '/usr/bin/freshclam', +      hasrestart => true, +      require    => Package['clamav-freshclam']; +  } + +  file_line { +    'freshclam_notify': +      path    => '/etc/clamav/freshclam.conf', +      line    => 'NotifyClamd /etc/clamav/clamd.conf', +      require => Package['clamav-freshclam'], +      notify  => Service['freshclam']; +  } + +} diff --git a/puppet/modules/clamav/manifests/init.pp b/puppet/modules/clamav/manifests/init.pp new file mode 100644 index 00000000..de8fb4dc --- /dev/null +++ b/puppet/modules/clamav/manifests/init.pp @@ -0,0 +1,8 @@ +class clamav { + +  include clamav::daemon +  include clamav::milter +  include clamav::unofficial_sigs +  include clamav::freshclam + +} diff --git a/puppet/modules/clamav/manifests/milter.pp b/puppet/modules/clamav/manifests/milter.pp new file mode 100644 index 00000000..e8a85e3f --- /dev/null +++ b/puppet/modules/clamav/manifests/milter.pp @@ -0,0 +1,50 @@ +class clamav::milter { + +  $clamav                = hiera('clamav') +  $whitelisted_addresses = $clamav['whitelisted_addresses'] +  $domain_hash           = hiera('domain') +  $domain                = $domain_hash['full_suffix'] + +  package { 'clamav-milter': ensure => installed } + +  service { +    'clamav-milter': +      ensure     => running, +      enable     => true, +      name       => clamav-milter, +      pattern    => '/usr/sbin/clamav-milter', +      hasrestart => true, +      require    => Package['clamav-milter'], +      subscribe  => File['/etc/default/clamav-milter']; +  } + +  file { +    '/run/clamav/milter.ctl': +      mode    => '0666', +      owner   => clamav, +      group   => postfix, +      require => Class['clamav::daemon']; + +    '/etc/clamav/clamav-milter.conf': +      content   => template('clamav/clamav-milter.conf.erb'), +      mode      => '0644', +      owner     => root, +      group     => root, +      require   => Package['clamav-milter'], +      subscribe => Service['clamav-milter']; + +    '/etc/default/clamav-milter': +      source => 'puppet:///modules/clamav/clamav-milter_default', +      mode   => '0644', +      owner  => root, +      group  => root; + +    '/etc/clamav/whitelisted_addresses': +      content => template('clamav/whitelisted_addresses.erb'), +      mode    => '0644', +      owner   => root, +      group   => root, +      require => Package['clamav-milter']; +  } + +} diff --git a/puppet/modules/clamav/manifests/unofficial_sigs.pp b/puppet/modules/clamav/manifests/unofficial_sigs.pp new file mode 100644 index 00000000..2d849585 --- /dev/null +++ b/puppet/modules/clamav/manifests/unofficial_sigs.pp @@ -0,0 +1,23 @@ +class clamav::unofficial_sigs { + +  package { 'clamav-unofficial-sigs': +    ensure => installed +  } + +  ensure_packages(['wget', 'gnupg', 'socat', 'rsync', 'curl']) + +  file { +    '/var/log/clamav-unofficial-sigs.log': +      ensure  => file, +      owner   => clamav, +      group   => clamav, +      require => Package['clamav-unofficial-sigs']; + +    '/etc/clamav-unofficial-sigs.conf.d/01-leap.conf': +      source  => 'puppet:///modules/clamav/01-leap.conf', +      mode    => '0755', +      owner   => root, +      group   => root, +      require => Package['clamav-unofficial-sigs']; +    } +} diff --git a/puppet/modules/clamav/templates/clamav-milter.conf.erb b/puppet/modules/clamav/templates/clamav-milter.conf.erb new file mode 100644 index 00000000..9bf7099e --- /dev/null +++ b/puppet/modules/clamav/templates/clamav-milter.conf.erb @@ -0,0 +1,28 @@ +# THIS FILE MANAGED BY PUPPET +MilterSocket /var/run/clamav/milter.ctl +FixStaleSocket true +User clamav +MilterSocketGroup clamav +MilterSocketMode 666 +AllowSupplementaryGroups true +ReadTimeout 120 +Foreground false +PidFile /var/run/clamav/clamav-milter.pid +ClamdSocket unix:/var/run/clamav/clamd.ctl +OnClean Accept +OnInfected Reject +OnFail Defer +AddHeader Replace +LogSyslog true +LogFacility LOG_LOCAL6 +LogVerbose yes +LogInfected Basic +LogTime true +LogFileUnlock false +LogClean Off +LogRotate true +SupportMultipleRecipients false +MaxFileSize 10M +TemporaryDirectory /var/tmp +RejectMsg "Message refused due to content violation: %v - contact https://<%= @domain %>/tickets/new if this is in error" +Whitelist /etc/clamav/whitelisted_addresses diff --git a/puppet/modules/clamav/templates/local.pdb.erb b/puppet/modules/clamav/templates/local.pdb.erb new file mode 100644 index 00000000..9ea0584a --- /dev/null +++ b/puppet/modules/clamav/templates/local.pdb.erb @@ -0,0 +1 @@ +H:<%= @domain %> diff --git a/puppet/modules/clamav/templates/whitelisted_addresses.erb b/puppet/modules/clamav/templates/whitelisted_addresses.erb new file mode 100644 index 00000000..9e068ec5 --- /dev/null +++ b/puppet/modules/clamav/templates/whitelisted_addresses.erb @@ -0,0 +1,5 @@ +<%- if @whitelisted_addresses then -%> +<%   @whitelisted_addresses.each do |name| -%> +From::<%= name %> +<%   end -%> +<% end -%> diff --git a/puppet/modules/common/LICENSE b/puppet/modules/common/LICENSE new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/puppet/modules/common/LICENSE @@ -0,0 +1,674 @@ +                    GNU GENERAL PUBLIC LICENSE +                       Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +                            Preamble + +  The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +  The licenses for most software and other practical works are designed +to take away your freedom to share and change the works.  By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users.  We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors.  You can apply it to +your programs, too. + +  When we speak of free software, we are referring to freedom, not +price.  Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +  To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights.  Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received.  You must make sure that they, too, receive +or can get the source code.  And you must show them these terms so they +know their rights. + +  Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +  For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software.  For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +  Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so.  This is fundamentally incompatible with the aim of +protecting users' freedom to change the software.  The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable.  Therefore, we +have designed this version of the GPL to prohibit the practice for those +products.  If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + +  Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary.  To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + +  The precise terms and conditions for copying, distribution and +modification follow. + +                       TERMS AND CONDITIONS + +  0. Definitions. + +  "This License" refers to version 3 of the GNU General Public License. + +  "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +  "The Program" refers to any copyrightable work licensed under this +License.  Each licensee is addressed as "you".  "Licensees" and +"recipients" may be individuals or organizations. + +  To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy.  The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + +  A "covered work" means either the unmodified Program or a work based +on the Program. + +  To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy.  Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +  To "convey" a work means any kind of propagation that enables other +parties to make or receive copies.  Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +  An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License.  If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +  1. Source Code. + +  The "source code" for a work means the preferred form of the work +for making modifications to it.  "Object code" means any non-source +form of a work. + +  A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +  The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form.  A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +  The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities.  However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work.  For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +  The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +  The Corresponding Source for a work in source code form is that +same work. + +  2. Basic Permissions. + +  All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met.  This License explicitly affirms your unlimited +permission to run the unmodified Program.  The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work.  This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +  You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force.  You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright.  Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +  Conveying under any other circumstances is permitted solely under +the conditions stated below.  Sublicensing is not allowed; section 10 +makes it unnecessary. + +  3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +  No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +  When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +  4. Conveying Verbatim Copies. + +  You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +  You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +  5. Conveying Modified Source Versions. + +  You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +    a) The work must carry prominent notices stating that you modified +    it, and giving a relevant date. + +    b) The work must carry prominent notices stating that it is +    released under this License and any conditions added under section +    7.  This requirement modifies the requirement in section 4 to +    "keep intact all notices". + +    c) You must license the entire work, as a whole, under this +    License to anyone who comes into possession of a copy.  This +    License will therefore apply, along with any applicable section 7 +    additional terms, to the whole of the work, and all its parts, +    regardless of how they are packaged.  This License gives no +    permission to license the work in any other way, but it does not +    invalidate such permission if you have separately received it. + +    d) If the work has interactive user interfaces, each must display +    Appropriate Legal Notices; however, if the Program has interactive +    interfaces that do not display Appropriate Legal Notices, your +    work need not make them do so. + +  A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit.  Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +  6. Conveying Non-Source Forms. + +  You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +    a) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by the +    Corresponding Source fixed on a durable physical medium +    customarily used for software interchange. + +    b) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by a +    written offer, valid for at least three years and valid for as +    long as you offer spare parts or customer support for that product +    model, to give anyone who possesses the object code either (1) a +    copy of the Corresponding Source for all the software in the +    product that is covered by this License, on a durable physical +    medium customarily used for software interchange, for a price no +    more than your reasonable cost of physically performing this +    conveying of source, or (2) access to copy the +    Corresponding Source from a network server at no charge. + +    c) Convey individual copies of the object code with a copy of the +    written offer to provide the Corresponding Source.  This +    alternative is allowed only occasionally and noncommercially, and +    only if you received the object code with such an offer, in accord +    with subsection 6b. + +    d) Convey the object code by offering access from a designated +    place (gratis or for a charge), and offer equivalent access to the +    Corresponding Source in the same way through the same place at no +    further charge.  You need not require recipients to copy the +    Corresponding Source along with the object code.  If the place to +    copy the object code is a network server, the Corresponding Source +    may be on a different server (operated by you or a third party) +    that supports equivalent copying facilities, provided you maintain +    clear directions next to the object code saying where to find the +    Corresponding Source.  Regardless of what server hosts the +    Corresponding Source, you remain obligated to ensure that it is +    available for as long as needed to satisfy these requirements. + +    e) Convey the object code using peer-to-peer transmission, provided +    you inform other peers where the object code and Corresponding +    Source of the work are being offered to the general public at no +    charge under subsection 6d. + +  A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +  A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling.  In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage.  For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product.  A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +  "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source.  The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +  If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information.  But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +  The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed.  Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +  Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +  7. Additional Terms. + +  "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law.  If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +  When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it.  (Additional permissions may be written to require their own +removal in certain cases when you modify the work.)  You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +  Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +    a) Disclaiming warranty or limiting liability differently from the +    terms of sections 15 and 16 of this License; or + +    b) Requiring preservation of specified reasonable legal notices or +    author attributions in that material or in the Appropriate Legal +    Notices displayed by works containing it; or + +    c) Prohibiting misrepresentation of the origin of that material, or +    requiring that modified versions of such material be marked in +    reasonable ways as different from the original version; or + +    d) Limiting the use for publicity purposes of names of licensors or +    authors of the material; or + +    e) Declining to grant rights under trademark law for use of some +    trade names, trademarks, or service marks; or + +    f) Requiring indemnification of licensors and authors of that +    material by anyone who conveys the material (or modified versions of +    it) with contractual assumptions of liability to the recipient, for +    any liability that these contractual assumptions directly impose on +    those licensors and authors. + +  All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10.  If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term.  If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +  If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +  Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +  8. Termination. + +  You may not propagate or modify a covered work except as expressly +provided under this License.  Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +  However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +  Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +  Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License.  If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +  9. Acceptance Not Required for Having Copies. + +  You are not required to accept this License in order to receive or +run a copy of the Program.  Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance.  However, +nothing other than this License grants you permission to propagate or +modify any covered work.  These actions infringe copyright if you do +not accept this License.  Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +  10. Automatic Licensing of Downstream Recipients. + +  Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License.  You are not responsible +for enforcing compliance by third parties with this License. + +  An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations.  If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +  You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License.  For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +  11. Patents. + +  A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based.  The +work thus licensed is called the contributor's "contributor version". + +  A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version.  For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +  Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +  In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement).  To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +  If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients.  "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +  If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +  A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License.  You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +  Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +  12. No Surrender of Others' Freedom. + +  If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License.  If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all.  For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +  13. Use with the GNU Affero General Public License. + +  Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work.  The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +  14. Revised Versions of this License. + +  The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time.  Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +  Each version is given a distinguishing version number.  If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation.  If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + +  If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +  Later license versions may give you additional or different +permissions.  However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +  15. Disclaimer of Warranty. + +  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +  16. Limitation of Liability. + +  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +  17. Interpretation of Sections 15 and 16. + +  If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +                     END OF TERMS AND CONDITIONS + +            How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + +    <one line to give the program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    This program is free software: you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation, either version 3 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program.  If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + +  If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +    <program>  Copyright (C) <year>  <name of author> +    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + +  You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + +  The GNU General Public License does not permit incorporating your program +into proprietary programs.  If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library.  If this is what you want to do, use the GNU Lesser General +Public License instead of this License.  But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/puppet/modules/common/README b/puppet/modules/common/README new file mode 100644 index 00000000..e6df7663 --- /dev/null +++ b/puppet/modules/common/README @@ -0,0 +1,44 @@ +Common Module +------------- + +The common module installs various functions that are required by other +modules. This module should be installed before any of the other module. + +! Upgrade Notice ! + +The 'append_if_no_such_line' define has been replaced with the 'line' define. If +you are using 'append_if_no_such_line' anywhere in your manifests, you will need +to transition to 'line' before upgrading to this version of the common +module. The 'line' define is a drop-in replacement and essentially equivalent, +so the transition is quite easy, you should only simply need to change the name +in your manifests. + +To use this module, follow these directions: + +1. Your modules directory will need all the files included in this +   repository placed under a directory called "common" + +2. Add the following line to manifests/site.pp: +    +       import "modules.pp" + +3. Add the following line to manifests/modules.pp: + +       import "common" + + +Original author: David Schmitt (mailto:david@dasz.at) +Copyright:: Copyright (c) 2007-2009 dasz.at OG +License::   3-clause BSD + +Additional authors: +Copyright (C) 2007 David Schmitt <david@schmitt.edv-bus.at> +Copyright 2008-2011, admin(at)immerda.ch +Copyright 2008, Puzzle ITC GmbH + Marcel Härry haerry+puppet(at)puzzle.ch + Simon Josi josi+puppet(at)puzzle.ch +Copyright 2009-2011, Riseup Labs <http://riseuplabs.org> + Pietro Ferrari <pietro@riseup.net> + Micah Anderson <micah@riseup.net> +Copyright (C) 2007 Antoine Beaupre <anarcat@koumbit.org> +Copyright (c) 2011 intrigeri - intrigeri(at)boum.org
\ No newline at end of file diff --git a/puppet/modules/common/lib/puppet/parser/functions/basename.rb b/puppet/modules/common/lib/puppet/parser/functions/basename.rb new file mode 100644 index 00000000..dc725375 --- /dev/null +++ b/puppet/modules/common/lib/puppet/parser/functions/basename.rb @@ -0,0 +1,22 @@ +# This function has two modes of operation: +# +#  basename(string) : string +# +# Returns the last component of the filename given as argument, which must be +# formed using forward slashes ("/") regardless of the separator used on the +# local file system. +# +#  basename(string[]) : string[] +# +# Returns an array of strings with the basename of each item from the argument. +# +module Puppet::Parser::Functions +	newfunction(:basename, :type => :rvalue) do |args| +		if args[0].is_a?(Array) +			args.collect do |a| File.basename(a) end +		else +			File.basename(args[0]) +		end +	end +end + diff --git a/puppet/modules/common/lib/puppet/parser/functions/dirname.rb b/puppet/modules/common/lib/puppet/parser/functions/dirname.rb new file mode 100644 index 00000000..ea0d50b4 --- /dev/null +++ b/puppet/modules/common/lib/puppet/parser/functions/dirname.rb @@ -0,0 +1,22 @@ +# This function has two modes of operation: +#  +#  dirname(string) : string +# +# Returns all components of the filename given as argument except the last +# one. The filename must be formed using forward slashes (``/..) regardless of +# the separator used on the local file system. +# +#  dirname(string[]) : string[] +# +# Returns an array of strings with the basename of each item from the argument.  +# +module Puppet::Parser::Functions +	newfunction(:dirname, :type => :rvalue) do |args| +		if args[0].is_a?(Array) +			args.collect do |a| File.dirname(a) end +		else +			File.dirname(args[0]) +		end +	end +end + diff --git a/puppet/modules/common/lib/puppet/parser/functions/get_default.rb b/puppet/modules/common/lib/puppet/parser/functions/get_default.rb new file mode 100644 index 00000000..3f4359bd --- /dev/null +++ b/puppet/modules/common/lib/puppet/parser/functions/get_default.rb @@ -0,0 +1,15 @@ +# get_default($value, $default) : $value +# +# return $value || $default. +module Puppet::Parser::Functions +    newfunction(:get_default, :type => :rvalue) do |args| +        value = nil +        args.each { |x| +            if ! x.nil? and x.length > 0 +                value = x +                break +            end +        } +        return value +    end +end diff --git a/puppet/modules/common/lib/puppet/parser/functions/hostname.rb b/puppet/modules/common/lib/puppet/parser/functions/hostname.rb new file mode 100644 index 00000000..7bc477f2 --- /dev/null +++ b/puppet/modules/common/lib/puppet/parser/functions/hostname.rb @@ -0,0 +1,13 @@ +# get an uniq array of ipaddresses for a hostname +require 'resolv' + +module Puppet::Parser::Functions +	newfunction(:hostname, :type => :rvalue) do |args| +        res = Array.new +        Resolv::DNS.new.each_address(args[0]){ |addr| +            res << addr +        } +        res.uniq +	end +end + diff --git a/puppet/modules/common/lib/puppet/parser/functions/multi_source_template.rb b/puppet/modules/common/lib/puppet/parser/functions/multi_source_template.rb new file mode 100644 index 00000000..e0753205 --- /dev/null +++ b/puppet/modules/common/lib/puppet/parser/functions/multi_source_template.rb @@ -0,0 +1,29 @@ +module Puppet::Parser::Functions +    require 'erb' + +    newfunction(:multi_source_template, :type => :rvalue) do |args| +        contents = nil +        environment = compiler.environment +        sources = args + +        sources.each do |file| +            Puppet.debug("Looking for #{file} in #{environment}") +            if filename = Puppet::Parser::Files.find_template(file, environment.to_s) +                wrapper = Puppet::Parser::TemplateWrapper.new(self) +                wrapper.file = file + +                begin +                     contents = wrapper.result +                rescue => detail +                     raise Puppet::ParseError, "Failed to parse template %s: %s" % [file, detail] +                end + +                break +            end +        end + +        raise Puppet::ParseError, "multi_source_template: No match found for files: #{sources.join(', ')}" if contents == nil + +        contents +    end +end diff --git a/puppet/modules/common/lib/puppet/parser/functions/prefix_with.rb b/puppet/modules/common/lib/puppet/parser/functions/prefix_with.rb new file mode 100644 index 00000000..6e64a4a8 --- /dev/null +++ b/puppet/modules/common/lib/puppet/parser/functions/prefix_with.rb @@ -0,0 +1,9 @@ +# prefix arguments 2..n with first argument + +module Puppet::Parser::Functions +	newfunction(:prefix_with, :type => :rvalue) do |args| +		prefix = args.shift +		args.collect {|v| "%s%s" % [prefix, v] } +	end +end + diff --git a/puppet/modules/common/lib/puppet/parser/functions/re_escape.rb b/puppet/modules/common/lib/puppet/parser/functions/re_escape.rb new file mode 100644 index 00000000..7bee90a8 --- /dev/null +++ b/puppet/modules/common/lib/puppet/parser/functions/re_escape.rb @@ -0,0 +1,7 @@ +# apply ruby regexp escaping to a string +module Puppet::Parser::Functions +	newfunction(:re_escape, :type => :rvalue) do |args| +		Regexp.escape(args[0]) +	end +end + diff --git a/puppet/modules/common/lib/puppet/parser/functions/slash_escape.rb b/puppet/modules/common/lib/puppet/parser/functions/slash_escape.rb new file mode 100644 index 00000000..04d3b95e --- /dev/null +++ b/puppet/modules/common/lib/puppet/parser/functions/slash_escape.rb @@ -0,0 +1,7 @@ +# escape slashes in a String +module Puppet::Parser::Functions +	newfunction(:slash_escape, :type => :rvalue) do |args| +		args[0].gsub(/\//, '\\/') +	end +end + diff --git a/puppet/modules/common/lib/puppet/parser/functions/substitute.rb b/puppet/modules/common/lib/puppet/parser/functions/substitute.rb new file mode 100644 index 00000000..4c97def3 --- /dev/null +++ b/puppet/modules/common/lib/puppet/parser/functions/substitute.rb @@ -0,0 +1,20 @@ +# subsititute($string, $regex, $replacement) : $string +# subsititute($string[], $regex, $replacement) : $string[] +# +# Replace all ocurrences of $regex in $string by $replacement. +# $regex is interpreted as Ruby regular expression. +# +# For long-term portability it is recommended to refrain from using Ruby's +# extended RE features. +module Puppet::Parser::Functions +	newfunction(:substitute, :type => :rvalue) do |args| +		if args[0].is_a?(Array) +			args[0].collect do |val| +				val.gsub(/#{args[1]}/, args[2]) +			end +		else +			args[0].gsub(/#{args[1]}/, args[2]) +		end +	end +end + diff --git a/puppet/modules/common/lib/puppet/parser/functions/tfile.rb b/puppet/modules/common/lib/puppet/parser/functions/tfile.rb new file mode 100644 index 00000000..acb6609b --- /dev/null +++ b/puppet/modules/common/lib/puppet/parser/functions/tfile.rb @@ -0,0 +1,19 @@ +Puppet::Parser::Functions::newfunction( +  :tfile, +  :type => :rvalue, +  :doc => "Returns the content of a file. If the file or the path does not +    yet exist, it will create the path and touch the file." +) do |args| +  raise Puppet::ParseError, 'tfile() needs one argument' if args.length != 1 +  path = args.to_a.first +  unless File.exists?(path) +    dir = File.dirname(path) +    unless File.directory?(dir) +      require 'fileutils' +      FileUtils.mkdir_p(dir, :mode => 0700) +    end +    require 'fileutils' +    FileUtils.touch(path) +  end +  File.read(path) +end diff --git a/puppet/modules/common/manifests/module_dir.pp b/puppet/modules/common/manifests/module_dir.pp new file mode 100644 index 00000000..2420da94 --- /dev/null +++ b/puppet/modules/common/manifests/module_dir.pp @@ -0,0 +1,34 @@ +# common/manifests/modules_dir.pp -- create a default directory +# for storing module specific information +# +# Copyright (C) 2007 David Schmitt <david@schmitt.edv-bus.at> +# See LICENSE for the full license granted to you. + +# A module_dir is a storage place for all the stuff a module might want to +# store. According to the FHS, this should go to /var/lib. Since this is a part +# of puppet, the full path is /var/lib/puppet/modules/${name}. Every module +# should # prefix its module_dirs with its name. +# +# Usage: +# include common::moduledir +# module_dir { ["common", "common/dir1", "common/dir2" ]: } +# +# You may refer to a file in module_dir by using : +# file { "${common::moduledir::module_dir_path}/somedir/somefile": } +define common::module_dir( +  $owner = root, +  $group = 0, +  $mode = 0644 +) { +  include common::moduledir +  file { +    "${common::moduledir::module_dir_path}/${name}": +      ensure    => directory, +      recurse   => true, +      purge     => true, +      force     => true, +      owner     => $owner, +      group     => $group, +      mode      => $mode; +  } +} diff --git a/puppet/modules/common/manifests/module_file.pp b/puppet/modules/common/manifests/module_file.pp new file mode 100644 index 00000000..c1070bcf --- /dev/null +++ b/puppet/modules/common/manifests/module_file.pp @@ -0,0 +1,37 @@ +# common/manifests/module_file.pp -- use a modules_dir to store module +# specific files +# +# Copyright (C) 2007 David Schmitt <david@schmitt.edv-bus.at> +# See LICENSE for the full license granted to you. + +# Put a file into module-local storage. +# +# Usage: +# common::module_file { "module/file": +#     source => "puppet:///...", +#     mode   => 644,   # default +#     owner  => root,  # default +#     group  => 0,     # default +# } +define common::module_file ( +  $ensure = present, +  $source = undef, +  $owner  = root, +  $group  = 0, +  $mode   = 0644 +){ +  include common::moduledir +  file { +    "${common::moduledir::module_dir_path}/${name}": +      ensure  => $ensure, +  } + +  if $ensure != 'absent' { +    File["${common::moduledir::module_dir_path}/${name}"]{ +      source  => $source, +      owner   => $owner, +      group   => $group, +      mode    => $mode, +    } +  } +} diff --git a/puppet/modules/common/manifests/moduledir.pp b/puppet/modules/common/manifests/moduledir.pp new file mode 100644 index 00000000..f779085b --- /dev/null +++ b/puppet/modules/common/manifests/moduledir.pp @@ -0,0 +1,18 @@ +# setup root for module_dirs +class common::moduledir { +  # Use this variable to reference the base path. Thus you are safe from any +  # changes. +  $module_dir_path = '/var/lib/puppet/modules' + +  # Module programmers can use /var/lib/puppet/modules/$modulename to save +  # module-local data, e.g. for constructing config files +  file{$module_dir_path: +    ensure  => directory, +    recurse => true, +    purge   => true, +    force   => true, +    owner   => root, +    group   => 0, +    mode    => '0755'; +  } +} diff --git a/puppet/modules/common/manifests/moduledir/common.pp b/puppet/modules/common/manifests/moduledir/common.pp new file mode 100644 index 00000000..e74c601e --- /dev/null +++ b/puppet/modules/common/manifests/moduledir/common.pp @@ -0,0 +1,4 @@ +# setup a common dir +class common::moduledir::common{ +  common::module_dir{'common': } +} diff --git a/puppet/modules/common/spec/spec.opts b/puppet/modules/common/spec/spec.opts new file mode 100644 index 00000000..91cd6427 --- /dev/null +++ b/puppet/modules/common/spec/spec.opts @@ -0,0 +1,6 @@ +--format +s +--colour +--loadby +mtime +--backtrace diff --git a/puppet/modules/common/spec/spec_helper.rb b/puppet/modules/common/spec/spec_helper.rb new file mode 100644 index 00000000..6ba62e11 --- /dev/null +++ b/puppet/modules/common/spec/spec_helper.rb @@ -0,0 +1,16 @@ +require 'pathname' +dir = Pathname.new(__FILE__).parent +$LOAD_PATH.unshift(dir, dir + 'lib', dir + '../lib') +require 'puppet' +gem 'rspec', '>= 1.2.9' +require 'spec/autorun' + +Dir[File.join(File.dirname(__FILE__), 'support', '*.rb')].each do |support_file| +  require support_file +end + +# We need this because the RAL uses 'should' as a method.  This +# allows us the same behaviour but with a different method name. +class Object +    alias :must :should +end diff --git a/puppet/modules/common/spec/unit/parser/functions/tfile.rb b/puppet/modules/common/spec/unit/parser/functions/tfile.rb new file mode 100644 index 00000000..5c8f636e --- /dev/null +++ b/puppet/modules/common/spec/unit/parser/functions/tfile.rb @@ -0,0 +1,54 @@ +#! /usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' +require 'mocha' + +describe "the tfile function" do + +  before :each do +    @scope = Puppet::Parser::Scope.new +  end + +  it "should exist" do +    Puppet::Parser::Functions.function("tfile").should == "function_tfile" +  end + +  it "should raise a ParseError if there is less than 1 arguments" do +    lambda { @scope.function_tfile([]) }.should( raise_error(Puppet::ParseError)) +  end + +  it "should raise a ParseError if there is more than 1 arguments" do +    lambda { @scope.function_tfile(["bar", "gazonk"]) }.should( raise_error(Puppet::ParseError)) +  end + +  describe "when executed properly" do + +    before :each do +       File.stubs(:read).with('/some_path/aa').returns("foo1\nfoo2\n") +    end + +    it "should return the content of the file" do +      File.stubs(:exists?).with('/some_path/aa').returns(true) +      result = @scope.function_tfile(['/some_path/aa']) +      result.should == "foo1\nfoo2\n" +    end + +    it "should touch a file if it does not exist" do +      File.stubs(:exists?).with('/some_path/aa').returns(false) +      File.stubs(:directory?).with('/some_path').returns(true) +      FileUtils.expects(:touch).with('/some_path/aa') +      result = @scope.function_tfile(['/some_path/aa']) +      result.should == "foo1\nfoo2\n" +    end + +    it "should create the path if it does not exist" do +      File.stubs(:exists?).with('/some_path/aa').returns(false) +      File.stubs(:directory?).with('/some_path').returns(false) +      FileUtils.expects(:mkdir_p).with("/some_path",:mode => 0700) +      FileUtils.expects(:touch).with('/some_path/aa') +      result = @scope.function_tfile(['/some_path/aa']) +      result.should == "foo1\nfoo2\n" +    end +  end + +end diff --git a/puppet/modules/concat/CHANGELOG b/puppet/modules/concat/CHANGELOG new file mode 100644 index 00000000..c506cf1a --- /dev/null +++ b/puppet/modules/concat/CHANGELOG @@ -0,0 +1,29 @@ +KNOWN ISSUES: +- In 0.24.8 you will see inintended notifies, if you build a file +  in a run, the next run will also see it as changed.  This is due +  to how 0.24.8 does the purging of unhandled files, this is improved +  in 0.25.x and we cannot work around it in our code. + +CHANGELOG: +- 2010/02/19 - initial release +- 2010/03/12 - add support for 0.24.8 and newer +             - make the location of sort configurable +             - add the ability to add shell comment based warnings to +               top of files +             - add the ablity to create empty files +- 2010/04/05 - fix parsing of WARN and change code style to match rest +               of the code +             - Better and safer boolean handling for warn and force +             - Don't use hard coded paths in the shell script, set PATH +               top of the script +             - Use file{} to copy the result and make all fragments owned +               by root.  This means we can chnage the ownership/group of the +               resulting file at any time. +             - You can specify ensure => "/some/other/file" in concat::fragment +               to include the contents of a symlink into the final file. +- 2010/04/16 - Add more cleaning of the fragment name - removing / from the $name +- 2010/05/22 - Improve documentation and show the use of ensure => +- 2010/07/14 - Add support for setting the filebucket behavior of files +- 2010/10/04 - Make the warning message configurable +- 2010/12/03 - Add flags to make concat work better on Solaris - thanks Jonathan Boyett +- 2011/02/03 - Make the shell script more portable and add a config option for root group diff --git a/puppet/modules/concat/LICENSE b/puppet/modules/concat/LICENSE new file mode 100644 index 00000000..6a9e9a19 --- /dev/null +++ b/puppet/modules/concat/LICENSE @@ -0,0 +1,14 @@ +   Copyright 2012 R.I.Pienaar + +   Licensed under the Apache License, Version 2.0 (the "License"); +   you may not use this file except in compliance with the License. +   You may obtain a copy of the License at + +     http://www.apache.org/licenses/LICENSE-2.0 + +   Unless required by applicable law or agreed to in writing, software +   distributed under the License is distributed on an "AS IS" BASIS, +   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +   See the License for the specific language governing permissions and +   limitations under the License. + diff --git a/puppet/modules/concat/Modulefile b/puppet/modules/concat/Modulefile new file mode 100644 index 00000000..d6ab2bb0 --- /dev/null +++ b/puppet/modules/concat/Modulefile @@ -0,0 +1,8 @@ +name 'puppet-concat' +version '0.1.0' +source 'git://github.com/ripienaar/puppet-concat.git' +author 'R.I.Pienaar' +license 'Apache' +summary 'Concat module' +description 'Concat module' +project_page 'http://github.com/ripienaar/puppet-concat' diff --git a/puppet/modules/concat/README.markdown b/puppet/modules/concat/README.markdown new file mode 100644 index 00000000..8736d57a --- /dev/null +++ b/puppet/modules/concat/README.markdown @@ -0,0 +1,112 @@ +What is it? +=========== + +A Puppet module that can construct files from fragments. + +Please see the comments in the various .pp files for details +as well as posts on my blog at http://www.devco.net/ + +Released under the Apache 2.0 licence + +Usage: +------ + +Before you can use any of the concat features you should include the class +concat::setup somewhere on your node first. + +If you wanted a /etc/motd file that listed all the major modules +on the machine.  And that would be maintained automatically even +if you just remove the include lines for other modules you could +use code like below, a sample /etc/motd would be: + +<pre> +Puppet modules on this server: + +    -- Apache +    -- MySQL +</pre> + +Local sysadmins can also append to the file by just editing /etc/motd.local +their changes will be incorporated into the puppet managed motd. + +<pre> +# class to setup basic motd, include on all nodes +class motd { +   include concat::setup +   $motd = "/etc/motd" + +   concat{$motd: +      owner => root, +      group => root, +      mode  => 644 +   } + +   concat::fragment{"motd_header": +      target => $motd, +      content => "\nPuppet modules on this server:\n\n", +      order   => 01, +   } + +   # local users on the machine can append to motd by just creating +   # /etc/motd.local +   concat::fragment{"motd_local": +      target => $motd, +      ensure  => "/etc/motd.local", +      order   => 15 +   } +} + +# used by other modules to register themselves in the motd +define motd::register($content="", $order=10) { +   if $content == "" { +      $body = $name +   } else { +      $body = $content +   } + +   concat::fragment{"motd_fragment_$name": +      target  => "/etc/motd", +      content => "    -- $body\n" +   } +} + +# a sample apache module +class apache { +   include apache::install, apache::config, apache::service + +   motd::register{"Apache": } +} +</pre> + +Known Issues: +------------- +* In 0.24.8 you will see inintended notifies, if you build a file +  in a run, the next run will also see it as changed.  This is due +  to how 0.24.8 does the purging of unhandled files, this is improved +  in 0.25.x and we cannot work around it in our code. +* Since puppet-concat now relies on a fact for the concat directory, +  you will need to set up pluginsync = true for at least the first run. +  You have this issue if puppet fails to run on the client and you have +  a message similar to +  "err: Failed to apply catalog: Parameter path failed: File +  paths must be fully qualified, not 'undef' at [...]/concat/manifests/setup.pp:44". + +Contributors: +------------- +**Paul Elliot** + + * Provided 0.24.8 support, shell warnings and empty file creation support. + +**Chad Netzer** + + * Various patches to improve safety of file operations + * Symlink support + +**David Schmitt** + + * Patch to remove hard coded paths relying on OS path + * Patch to use file{} to copy the resulting file to the final destination.  This means Puppet client will show diffs and that hopefully we can change file ownerships now + +Contact: +-------- +You can contact me on rip@devco.net or follow my blog at http://www.devco.net I am also on twitter as ripienaar diff --git a/puppet/modules/concat/Rakefile b/puppet/modules/concat/Rakefile new file mode 100644 index 00000000..764aebd2 --- /dev/null +++ b/puppet/modules/concat/Rakefile @@ -0,0 +1,13 @@ +require 'rake' +require 'rspec/core/rake_task' + +task :default => [:spec] + +desc "Run all module spec tests (Requires rspec-puppet gem)" +RSpec::Core::RakeTask.new(:spec) + +desc "Build package" +task :build do +  system("puppet-module build") +end + diff --git a/puppet/modules/concat/files/concatfragments.sh b/puppet/modules/concat/files/concatfragments.sh new file mode 100755 index 00000000..c9397975 --- /dev/null +++ b/puppet/modules/concat/files/concatfragments.sh @@ -0,0 +1,129 @@ +#!/bin/sh + +# Script to concat files to a config file. +# +# Given a directory like this: +# /path/to/conf.d +# |-- fragments +# |   |-- 00_named.conf +# |   |-- 10_domain.net +# |   `-- zz_footer +# +# The script supports a test option that will build the concat file to a temp location and  +# use /usr/bin/cmp to verify if it should be run or not.  This would result in the concat happening +# twice on each run but gives you the option to have an unless option in your execs to inhibit rebuilds. +#  +# Without the test option and the unless combo your services that depend on the final file would end up  +# restarting on each run, or in other manifest models some changes might get missed. +# +# OPTIONS: +#  -o	The file to create from the sources +#  -d	The directory where the fragments are kept +#  -t	Test to find out if a build is needed, basically concats the files to a temp +#       location and compare with what's in the final location, return codes are designed +#       for use with unless on an exec resource +#  -w   Add a shell style comment at the top of the created file to warn users that it  +#       is generated by puppet +#  -f   Enables the creation of empty output files when no fragments are found +#  -n	Sort the output numerically rather than the default alpha sort +# +# the command:  +# +#   concatfragments.sh -o /path/to/conffile.cfg -d /path/to/conf.d +# +# creates /path/to/conf.d/fragments.concat and copies the resulting  +# file to /path/to/conffile.cfg.  The files will be sorted alphabetically +# pass the -n switch to sort numerically. +#  +# The script does error checking on the various dirs and files to make +# sure things don't fail. + +OUTFILE="" +WORKDIR="" +TEST="" +FORCE="" +WARN="" +SORTARG="" + +PATH=/sbin:/usr/sbin:/bin:/usr/bin + +## Well, if there's ever a bad way to do things, Nexenta has it. +## http://nexenta.org/projects/site/wiki/Personalities +unset SUN_PERSONALITY + +while getopts "o:s:d:tnw:f" options; do +	case $options in +		o ) OUTFILE=$OPTARG;; +		d ) WORKDIR=$OPTARG;; +		n ) SORTARG="-n";; +		w ) WARNMSG="$OPTARG";; +		f ) FORCE="true";; +		t ) TEST="true";; +		* ) echo "Specify output file with -o and fragments directory with -d" +		    exit 1;; +	esac +done + +# do we have -o? +if [ x${OUTFILE} = "x" ]; then +	echo "Please specify an output file with -o" +	exit 1 +fi + +# do we have -d? +if [ x${WORKDIR} = "x" ]; then +	echo "Please fragments directory with -d" +	exit 1 +fi + +# can we write to -o? +if [ -f ${OUTFILE} ]; then +	if [ ! -w ${OUTFILE} ]; then +		echo "Cannot write to ${OUTFILE}" +		exit 1 +	fi +else +	if [ ! -w `dirname ${OUTFILE}` ]; then +		echo "Cannot write to `dirname ${OUTFILE}` to create ${OUTFILE}" +		exit 1 +	fi +fi + +# do we have a fragments subdir inside the work dir? +if [ ! -d "${WORKDIR}/fragments" ]  && [ ! -x "${WORKDIR}/fragments" ]; then +	echo "Cannot access the fragments directory" +	exit 1 +fi + +# are there actually any fragments? +if [ ! "$(ls -A ${WORKDIR}/fragments)" ]; then +	if [ x${FORCE} = "x" ]; then +		echo "The fragments directory is empty, cowardly refusing to make empty config files" +		exit 1 +	fi +fi + +cd ${WORKDIR} + +if [ x${WARNMSG} = "x" ]; then +	: > "fragments.concat" +else +	printf '%s\n' "$WARNMSG" > "fragments.concat" +fi + +# find all the files in the fragments directory, sort them numerically and concat to fragments.concat in the working dir +find fragments/ -type f -follow | sort ${SORTARG} | while read fragfile; do +	cat "$fragfile" >> "fragments.concat" +done + +if [ x${TEST} = "x" ]; then +	# This is a real run, copy the file to outfile +	cp fragments.concat ${OUTFILE} +	RETVAL=$? +else +	# Just compare the result to outfile to help the exec decide +	cmp ${OUTFILE} fragments.concat +	RETVAL=$? +fi + +exit $RETVAL diff --git a/puppet/modules/concat/files/null/.gitignore b/puppet/modules/concat/files/null/.gitignore new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/puppet/modules/concat/files/null/.gitignore diff --git a/puppet/modules/concat/lib/facter/concat_basedir.rb b/puppet/modules/concat/lib/facter/concat_basedir.rb new file mode 100644 index 00000000..02e9c5bf --- /dev/null +++ b/puppet/modules/concat/lib/facter/concat_basedir.rb @@ -0,0 +1,5 @@ +Facter.add("concat_basedir") do +    setcode do +        File.join(Puppet[:vardir],"concat") +    end +end diff --git a/puppet/modules/concat/manifests/fragment.pp b/puppet/modules/concat/manifests/fragment.pp new file mode 100644 index 00000000..943bf671 --- /dev/null +++ b/puppet/modules/concat/manifests/fragment.pp @@ -0,0 +1,49 @@ +# Puts a file fragment into a directory previous setup using concat +#  +# OPTIONS: +#   - target    The file that these fragments belong to +#   - content   If present puts the content into the file +#   - source    If content was not specified, use the source +#   - order     By default all files gets a 10_ prefix in the directory +#               you can set it to anything else using this to influence the +#               order of the content in the file +#   - ensure    Present/Absent or destination to a file to include another file +#   - mode      Mode for the file +#   - owner     Owner of the file +#   - group     Owner of the file +#   - backup    Controls the filebucketing behavior of the final file and +#               see File type reference for its use.  Defaults to 'puppet' +define concat::fragment($target, $content='', $source='', $order=10, $ensure = 'present', $mode = '0644', $owner = $::id, $group = $concat::setup::root_group, $backup = 'puppet') { +  $safe_name = regsubst($name, '/', '_', 'G') +  $safe_target_name = regsubst($target, '/', '_', 'G') +  $concatdir = $concat::setup::concatdir +  $fragdir = "${concatdir}/${safe_target_name}" + +  # if content is passed, use that, else if source is passed use that +  # if neither passed, but $ensure is in symlink form, make a symlink +  case $content { +    '': { +      case $source { +        '': { +          case $ensure { +            '', 'absent', 'present', 'file', 'directory': { +              crit('No content, source or symlink specified') +            } +          } +        } +        default: { File{ source => $source } } +      } +    } +    default: { File{ content => $content } } +  } + +  file{"${fragdir}/fragments/${order}_${safe_name}": +    ensure => $ensure, +    mode   => $mode, +    owner  => $owner, +    group  => $group, +    backup => $backup, +    alias  => "concat_fragment_${name}", +    notify => Exec["concat_${target}"] +  } +} diff --git a/puppet/modules/concat/manifests/init.pp b/puppet/modules/concat/manifests/init.pp new file mode 100644 index 00000000..0b3ed564 --- /dev/null +++ b/puppet/modules/concat/manifests/init.pp @@ -0,0 +1,178 @@ +# A system to construct files using fragments from other files or templates. +# +# This requires at least puppet 0.25 to work correctly as we use some +# enhancements in recursive directory management and regular expressions +# to do the work here. +# +# USAGE: +# The basic use case is as below: +# +# concat{"/etc/named.conf": +#    notify => Service["named"] +# } +# +# concat::fragment{"foo.com_config": +#    target  => "/etc/named.conf", +#    order   => 10, +#    content => template("named_conf_zone.erb") +# } +# +# # add a fragment not managed by puppet so local users +# # can add content to managed file +# concat::fragment{"foo.com_user_config": +#    target  => "/etc/named.conf", +#    order   => 12, +#    ensure  => "/etc/named.conf.local" +# } +# +# This will use the template named_conf_zone.erb to build a single +# bit of config up and put it into the fragments dir.  The file +# will have an number prefix of 10, you can use the order option +# to control that and thus control the order the final file gets built in. +# +# SETUP: +# The class concat::setup uses the fact concat_basedir to define the variable +# $concatdir, where all the temporary files and fragments will be +# durably stored. The fact concat_basedir will be set up on the client to +# <Puppet[:vardir]>/concat, so you will be able to run different setup/flavours +# of puppet clients. +# However, since this requires the file lib/facter/concat_basedir.rb to be +# deployed on the clients, so you will have to set "pluginsync = true" on +# both the master and client, at least for the first run. +# +# There's some regular expression magic to figure out the puppet version but +# if you're on an older 0.24 version just set $puppetversion = 24 +# +# Before you can use any of the concat features you should include the +# class concat::setup somewhere on your node first. +# +# DETAIL: +# We use a helper shell script called concatfragments.sh that gets placed +# in <Puppet[:vardir]>/concat/bin to do the concatenation.  While this might +# seem more complex than some of the one-liner alternatives you might find on +# the net we do a lot of error checking and safety checks in the script to avoid +# problems that might be caused by complex escaping errors etc. +# +# LICENSE: +# Apache Version 2 +# +# LATEST: +# http://github.com/ripienaar/puppet-concat/ +# +# CONTACT: +# R.I.Pienaar <rip@devco.net> +# Volcane on freenode +# @ripienaar on twitter +# www.devco.net + + +# Sets up so that you can use fragments to build a final config file, +# +# OPTIONS: +#  - mode       The mode of the final file +#  - owner      Who will own the file +#  - group      Who will own the file +#  - force      Enables creating empty files if no fragments are present +#  - warn       Adds a normal shell style comment top of the file indicating +#               that it is built by puppet +#  - backup     Controls the filebucketing behavior of the final file and +#               see File type reference for its use.  Defaults to 'puppet' +# +# ACTIONS: +#  - Creates fragment directories if it didn't exist already +#  - Executes the concatfragments.sh script to build the final file, this script will create +#    directory/fragments.concat.   Execution happens only when: +#    * The directory changes +#    * fragments.concat != final destination, this means rebuilds will happen whenever +#      someone changes or deletes the final file.  Checking is done using /usr/bin/cmp. +#    * The Exec gets notified by something else - like the concat::fragment define +#  - Copies the file over to the final destination using a file resource +# +# ALIASES: +#  - The exec can notified using Exec["concat_/path/to/file"] or Exec["concat_/path/to/directory"] +#  - The final file can be referened as File["/path/to/file"] or File["concat_/path/to/file"] +define concat($mode = '0644', $owner = $::id, $group = $concat::setup::root_group, $warn = false, $force = false, $backup = 'puppet', $gnu = undef, $order='alpha') { +  $safe_name   = regsubst($name, '/', '_', 'G') +  $concatdir   = $concat::setup::concatdir +  $version     = $concat::setup::majorversion +  $fragdir     = "${concatdir}/${safe_name}" +  $concat_name = 'fragments.concat.out' +  $default_warn_message = '# This file is managed by Puppet. DO NOT EDIT.' + +  case $warn { +    'true',true,yes,on:   { $warnmsg = $default_warn_message } +    'false',false,no,off: { $warnmsg = '' } +    default:              { $warnmsg = $warn } +  } + +  $warnmsg_escaped = regsubst($warnmsg, "'", "'\\\\''", 'G') +  $warnflag = $warnmsg_escaped ? { +    ''      => '', +    default => "-w '${warnmsg_escaped}'" +  } + +  case $force { +    'true',true,yes,on: { $forceflag = '-f' } +    'false',false,no,off: { $forceflag = '' } +    default: { fail("Improper 'force' value given to concat: ${force}") } +  } + +  case $order { +    numeric: { $orderflag = '-n' } +    alpha: { $orderflag = '' } +    default: { fail("Improper 'order' value given to concat: ${order}") } +  } + +  File{ +    owner  => $::id, +    group  => $group, +    mode   => $mode, +    backup => $backup +  } + +  file{$fragdir: +    ensure   => directory; + +  "${fragdir}/fragments": +    ensure   => directory, +    recurse  => true, +    purge    => true, +    force    => true, +    ignore   => ['.svn', '.git', '.gitignore'], +    source   => $version ? { +      24      => 'puppet:///concat/null', +      default => undef, +    }, +    notify   => Exec["concat_${name}"]; + +  "${fragdir}/fragments.concat": +    ensure   => present; + +  "${fragdir}/${concat_name}": +    ensure   => present; + +  $name: +    ensure   => present, +    source   => "${fragdir}/${concat_name}", +    owner    => $owner, +    group    => $group, +    checksum => md5, +    mode     => $mode, +    alias    => "concat_${name}"; +  } + +  exec{"concat_${name}": +    notify    => File[$name], +    subscribe => File[$fragdir], +    alias     => "concat_${fragdir}", +    require   => [ File[$fragdir], File["${fragdir}/fragments"], File["${fragdir}/fragments.concat"] ], +    unless    => "${concat::setup::concatdir}/bin/concatfragments.sh -o ${fragdir}/${concat_name} -d ${fragdir} -t ${warnflag} ${forceflag} ${orderflag}", +    command   => "${concat::setup::concatdir}/bin/concatfragments.sh -o ${fragdir}/${concat_name} -d ${fragdir} ${warnflag} ${forceflag} ${orderflag}", +  } +  if $::id == 'root' { +    Exec["concat_${name}"]{ +      user      => root, +      group     => $group, +    } +  } +} diff --git a/puppet/modules/concat/manifests/setup.pp b/puppet/modules/concat/manifests/setup.pp new file mode 100644 index 00000000..38aeb964 --- /dev/null +++ b/puppet/modules/concat/manifests/setup.pp @@ -0,0 +1,49 @@ +# Sets up the concat system. +# +# $concatdir is where the fragments live and is set on the fact concat_basedir. +# Since puppet should always manage files in $concatdir and they should +# not be deleted ever, /tmp is not an option. +# +# $puppetversion should be either 24 or 25 to enable a 24 compatible +# mode, in 24 mode you might see phantom notifies this is a side effect +# of the method we use to clear the fragments directory. +# +# The regular expression below will try to figure out your puppet version +# but this code will only work in 0.24.8 and newer. +# +# It also copies out the concatfragments.sh file to ${concatdir}/bin +class concat::setup { +  $id = $::id +  $root_group = $id ? { +    root    => 0, +    default => $id +  } + +  if $::concat_basedir { +    $concatdir = $::concat_basedir +  } else { +    fail ("\$concat_basedir not defined. Try running again with pluginsync enabled") +  } + +  $majorversion = regsubst($::puppetversion, '^[0-9]+[.]([0-9]+)[.][0-9]+$', '\1') + +  file{"${concatdir}/bin/concatfragments.sh": +    owner  => $id, +    group  => $root_group, +    mode   => '0755', +    source => $majorversion ? { +      24      => 'puppet:///concat/concatfragments.sh', +      default => 'puppet:///modules/concat/concatfragments.sh' +    }; + +  [ $concatdir, "${concatdir}/bin" ]: +    ensure => directory, +    owner  => $id, +    group  => $root_group, +    mode   => '0750'; + +  ## Old versions of this module used a different path. +  '/usr/local/bin/concatfragments.sh': +    ensure => absent; +  } +} diff --git a/puppet/modules/concat/spec/defines/init_spec.rb b/puppet/modules/concat/spec/defines/init_spec.rb new file mode 100644 index 00000000..d968a26c --- /dev/null +++ b/puppet/modules/concat/spec/defines/init_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe 'concat' do +  basedir = '/var/lib/puppet/concat' +  let(:title) { '/etc/foo.bar' } +  let(:facts) { { :concat_basedir => '/var/lib/puppet/concat' } } +  let :pre_condition do +    'include concat::setup' +  end +  it { should contain_file("#{basedir}/_etc_foo.bar").with('ensure' => 'directory') } +  it { should contain_file("#{basedir}/_etc_foo.bar/fragments").with('ensure' => 'directory') } + +  it { should contain_file("#{basedir}/_etc_foo.bar/fragments.concat").with('ensure' => 'present') } +  it { should contain_file("/etc/foo.bar").with('ensure' => 'present') } +  it { should contain_exec("concat_/etc/foo.bar").with_command( +                                        "#{basedir}/bin/concatfragments.sh "+ +                                        "-o #{basedir}/_etc_foo.bar/fragments.concat.out "+ +                                        "-d #{basedir}/_etc_foo.bar   ") +  } +end diff --git a/puppet/modules/concat/spec/spec_helper.rb b/puppet/modules/concat/spec/spec_helper.rb new file mode 100644 index 00000000..e6e9309b --- /dev/null +++ b/puppet/modules/concat/spec/spec_helper.rb @@ -0,0 +1,9 @@ +require 'puppet' +require 'rspec' +require 'rspec-puppet' + +RSpec.configure do |c| +  c.module_path = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures/modules/')) +  # Using an empty site.pp file to avoid: https://github.com/rodjek/rspec-puppet/issues/15 +  c.manifest_dir = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures/manifests')) +end diff --git a/puppet/modules/couchdb/.fixtures.yml b/puppet/modules/couchdb/.fixtures.yml new file mode 100644 index 00000000..50c6c9ac --- /dev/null +++ b/puppet/modules/couchdb/.fixtures.yml @@ -0,0 +1,6 @@ +fixtures: +  symlinks: +    couchdb: "#{source_dir}" +  repositories: +    stdlib:    " https://leap.se/git/puppet_stdlib" + diff --git a/puppet/modules/couchdb/Gemfile b/puppet/modules/couchdb/Gemfile new file mode 100644 index 00000000..1c86e980 --- /dev/null +++ b/puppet/modules/couchdb/Gemfile @@ -0,0 +1,11 @@ +source "https://rubygems.org" + +group :test do +  gem "rake" +  gem "puppet", ENV['PUPPET_VERSION'] || '~> 3.7.0' +  gem "rspec", '< 3.2.0' +  gem "rspec-puppet" +  gem "puppetlabs_spec_helper" +  gem "metadata-json-lint" +  gem "rspec-puppet-facts" +end diff --git a/puppet/modules/couchdb/README.md b/puppet/modules/couchdb/README.md new file mode 100644 index 00000000..096221a4 --- /dev/null +++ b/puppet/modules/couchdb/README.md @@ -0,0 +1,32 @@ +# Couchdb Puppet module + +This module is based on the one from Camptocamp_. + +.. _Camptocamp: http://www.camptocamp.com/ + +For more information about couchdb see http://couchdb.apache.org/ + +# Dependencies + +- ruby module from the shared-modules group + +# Couchdb debian packages + +## Jessie + +There are no couchdb packages for jessie, so the only way is to +to configure apt to install couchdb from unstable by adding a +sources list file to `/etc/apt/sources.list.d`. + +## Example usage + +This will setup couchdb: + +    # needed for wget call, which is unqualified by purpose so we don't force +    # a location for the wget binary +    Exec { path    => '/usr/bin:/usr/sbin/:/bin:/sbin:/usr/local/bin:/usr/local/sbin' } + +    class { 'couchdb': +      admin_pw => '123' +    } + diff --git a/puppet/modules/couchdb/Rakefile b/puppet/modules/couchdb/Rakefile new file mode 100644 index 00000000..85326bb4 --- /dev/null +++ b/puppet/modules/couchdb/Rakefile @@ -0,0 +1,19 @@ +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' +PuppetLint.configuration.send('disable_80chars') +PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "pkg/**/*.pp"] + +desc "Validate manifests, templates, and ruby files" +task :validate do +  Dir['manifests/**/*.pp'].each do |manifest| +    sh "puppet parser validate --noop #{manifest}" +  end +  Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file| +    sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/ +  end +  Dir['templates/**/*.erb'].each do |template| +    sh "erb -P -x -T '-' #{template} | ruby -c" +  end +end + +task :test => [:lint, :syntax , :validate, :spec] diff --git a/puppet/modules/couchdb/files/Debian/couchdb b/puppet/modules/couchdb/files/Debian/couchdb new file mode 100755 index 00000000..ccdfe716 --- /dev/null +++ b/puppet/modules/couchdb/files/Debian/couchdb @@ -0,0 +1,160 @@ +#!/bin/sh -e + +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +#   http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +### BEGIN INIT INFO +# Provides:          couchdb +# Required-Start:    $local_fs $remote_fs +# Required-Stop:     $local_fs $remote_fs +# Default-Start:     2 3 4 5 +# Default-Stop:      0 1 6 +# Short-Description: Apache CouchDB init script +# Description:       Apache CouchDB init script for the database server. +### END INIT INFO + +SCRIPT_OK=0 +SCRIPT_ERROR=1 + +DESCRIPTION="database server" +NAME=couchdb +SCRIPT_NAME=`basename $0` +COUCHDB=/usr/bin/couchdb +CONFIGURATION_FILE=/etc/default/couchdb +RUN_DIR=/var/run/couchdb +LSB_LIBRARY=/lib/lsb/init-functions + +if test ! -x $COUCHDB; then +    exit $SCRIPT_ERROR +fi + +if test -r $CONFIGURATION_FILE; then +    . $CONFIGURATION_FILE +fi + +log_daemon_msg () { +    # Dummy function to be replaced by LSB library. + +    echo $@ +} + +log_end_msg () { +    # Dummy function to be replaced by LSB library. + +    if test "$1" != "0"; then +      echo "Error with $DESCRIPTION: $NAME" +    fi +    return $1 +} + +if test -r $LSB_LIBRARY; then +    . $LSB_LIBRARY +fi + +run_command () { +    command="$1" +    if test -n "$COUCHDB_OPTIONS"; then +        command="$command $COUCHDB_OPTIONS" +    fi +    if test -n "$COUCHDB_USER"; then +        if su $COUCHDB_USER -c "$command"; then +            return $SCRIPT_OK +        else +            return $SCRIPT_ERROR +        fi +    else +        if $command; then +            return $SCRIPT_OK +        else +            return $SCRIPT_ERROR +        fi +    fi +} + +start_couchdb () { +    # Start Apache CouchDB as a background process. + +    mkdir -p "$RUN_DIR" +    chown -R "$COUCHDB_USER" "$RUN_DIR" +    command="$COUCHDB -b" +    if test -n "$COUCHDB_STDOUT_FILE"; then +        command="$command -o $COUCHDB_STDOUT_FILE" +    fi +    if test -n "$COUCHDB_STDERR_FILE"; then +        command="$command -e $COUCHDB_STDERR_FILE" +    fi +    if test -n "$COUCHDB_RESPAWN_TIMEOUT"; then +        command="$command -r $COUCHDB_RESPAWN_TIMEOUT" +    fi +    run_command "$command" > /dev/null +} + +stop_couchdb () { +    # Stop the running Apache CouchDB process. + +    run_command "$COUCHDB -d" > /dev/null +    pkill -u couchdb +    # always return true even if no remaining couchdb procs got killed +    /bin/true +} + +display_status () { +    # Display the status of the running Apache CouchDB process. + +    run_command "$COUCHDB -s" +} + +parse_script_option_list () { +    # Parse arguments passed to the script and take appropriate action. + +    case "$1" in +        start) +            log_daemon_msg "Starting $DESCRIPTION" $NAME +            if start_couchdb; then +                log_end_msg $SCRIPT_OK +            else +                log_end_msg $SCRIPT_ERROR +            fi +            ;; +        stop) +            log_daemon_msg "Stopping $DESCRIPTION" $NAME +            if stop_couchdb; then +                log_end_msg $SCRIPT_OK +            else +                log_end_msg $SCRIPT_ERROR +            fi +            ;; +        restart|force-reload) +            log_daemon_msg "Restarting $DESCRIPTION" $NAME +            if stop_couchdb; then +                if start_couchdb; then +                    log_end_msg $SCRIPT_OK +                else +                    log_end_msg $SCRIPT_ERROR +                fi +            else +                log_end_msg $SCRIPT_ERROR +            fi +            ;; +        status) +            display_status +            ;; +        *) +            cat << EOF >&2 +Usage: $SCRIPT_NAME {start|stop|restart|force-reload|status} +EOF +            exit $SCRIPT_ERROR +            ;; +    esac +} + +parse_script_option_list $@ diff --git a/puppet/modules/couchdb/files/couch-doc-diff b/puppet/modules/couchdb/files/couch-doc-diff new file mode 100644 index 00000000..a5907d5e --- /dev/null +++ b/puppet/modules/couchdb/files/couch-doc-diff @@ -0,0 +1,17 @@ +#!/bin/bash + +# Run a diff between a couch document specified as the first parameter +# and the second parameter. +# Diff returns 0 if there is no difference. This way you can tell the data +# is already on the couch. +# Both the couch document and the second paramter will be pretty printed +# before comparison so differences in spaces etc. do not matter. +# All keys starting with an underscore on the couch such as _id and _rev +# will be removed before the comparison - we assume we want to compare +# the real data, not the metadata about the document as we usually do not +# know or care about what the id and revision will be. + +curl -s --netrc-file /etc/couchdb/couchdb.netrc $1 \ + | python -mjson.tool \ + | grep -v '^\s*"_' \ + | diff -w - <(echo $2 | python -mjson.tool) diff --git a/puppet/modules/couchdb/files/couch-doc-update b/puppet/modules/couchdb/files/couch-doc-update new file mode 100644 index 00000000..a137e7ff --- /dev/null +++ b/puppet/modules/couchdb/files/couch-doc-update @@ -0,0 +1,219 @@ +#!/usr/bin/ruby +require 'syslog' + +# +# This script will delete or update the values of a particular couchdb document. The benefit of this little script over +# using a simple curl command for updating a document is this: +# +#   * exit non-zero status if document was not updated. +#   * updates existing documents easily, taking care of the _rev id for you. +#   * if document doesn't exist, it is created +# +# REQUIREMENTS +# +#   gem 'couchrest' +# +# USAGE +# +#   see the ouput of +# +#     couch-doc-update +# +#   the content of <file> will be merged with the data provided. +#   If you only want the file content use --data '{}' +# +# EXAMPLE +# +#   create a new user: +#     couch-doc-update --db _users --id org.couchdb.user:ca_daemon --data '{"type": "user", "name": "ca_daemon", "roles": ["certs"], "password": "sshhhh"}' +# +#   update a user: +#     couch-doc-update --db _users --id org.couchdb.user:ca_daemon --data '{"password":"sssshhh"}' +# +#   To update the _users DB on bigcouch, you must connect to port 5986 instead of the default couchdb port 5984 +# +#   delete a doc: +#     couch-doc-update --delete --db invite_codes --id dfaf0ee65670c16d5a9161dc86f3bff8 +# + +begin; require 'rubygems'; rescue LoadError; end # optionally load rubygems +require 'couchrest' + +def main +  db, id, data, delete = process_options + +  result = if delete +    delete_document(db, id) +  else +    set_document(db, id, data) +  end + +  exit 0 if result['ok'] +  raise StandardError.new(result.inspect) +rescue StandardError => exc +  db_without_password = db.to_s.sub(/:[^\/]*@/, ':PASSWORD_HIDDEN@') +  indent = "       " +  log "ERROR: " + exc.to_s +  log indent + $@[0..4].join("\n#{indent}") +  log indent + "Failed writing to #{db_without_password}/#{id}" +  exit 1 +end + +def log(message) +  $stderr.puts message +  Syslog.open('couch-doc-update') do |logger| +    logger.log(Syslog::LOG_CRIT, message) +  end +end + +def process_options +  # +  # parse options +  # +  host       = nil +  db_name    = nil +  doc_id     = nil +  new_data   = nil +  filename   = nil +  netrc_file = nil +  delete     = false +  loop do +    case ARGV[0] +      when '--host' then ARGV.shift; host     = ARGV.shift +      when '--db'   then ARGV.shift; db_name  = ARGV.shift +      when '--id'   then ARGV.shift; doc_id   = ARGV.shift +      when '--data' then ARGV.shift; new_data = ARGV.shift +      when '--file' then ARGV.shift; filename = ARGV.shift +      when '--netrc-file' then ARGV.shift; netrc_file = ARGV.shift +      when '--delete' then ARGV.shift; delete = true +      when /^-/     then usage("Unknown option: #{ARGV[0].inspect}") +      else break +    end +  end +  usage("Missing required option") unless db_name && doc_id && (new_data || delete) + +  unless delete +    new_data = MultiJson.load(new_data) +    new_data.merge!(read_file(filename)) if filename +  end +  db  = CouchRest.database(connection_string(db_name, host, netrc_file)) +  return db, doc_id, new_data, delete +end + +def read_file(filename) +  data = MultiJson.load( IO.read(filename) ) +  # strip off _id and _rev to avoid conflicts +  data.delete_if {|k,v| k.start_with? '_'} +end + +  # +  # update document +  # +def set_document(db, id, data) +  attempt ||= 1 +  doc = get_document(db, id) +  if doc +    doc.id ||= id +    update_document(db, doc, data) +  else +    create_document(db, id, data) +  end +rescue RestClient::Conflict +  # retry once, reraise if that does not work +  raise if attempt > 1 +  attempt += 1 +  retry +end + +COUCH_RESPONSE_OK = { 'ok' => true } + +# Deletes document, if exists, with retry +def delete_document(db, id) +  attempts ||= 1 +  doc = get_document(db, id) +  if doc +    db.delete_doc(doc) +  else +    COUCH_RESPONSE_OK +  end +rescue RestClient::ExceptionWithResponse => e +  if attempts < 6 && !e.response.nil? && RETRY_CODES.include?(e.response.code) +    attempts += 1 +    sleep 10 +    retry +  else +    raise e +  end +end + +def get_document(db, doc_id) +  begin +    db.get(doc_id) +  rescue RestClient::ResourceNotFound +    nil +  end +end + +# if the response status code is one of these +# then retry instead of failing. +RETRY_CODES = [500, 422].freeze + +def update_document(db, doc, data) +  attempts ||= 1 +  doc.reject! {|k,v| !["_id", "_rev"].include? k} +  doc.merge! data +  db.save_doc(doc) +rescue RestClient::ExceptionWithResponse => e +  if attempts < 6 && !e.response.nil? && RETRY_CODES.include?(e.response.code) +    attempts += 1 +    sleep 10 +    retry +  else +    raise e +  end +end + +def create_document(db, doc_id, data) +  attempts ||= 1 +  data["_id"] = doc_id +  db.save_doc(data) +rescue RestClient::ExceptionWithResponse => e +  if attempts < 6 && !e.response.nil? && RETRY_CODES.include?(e.response.code) +    attempts += 1 +    sleep 10 +    retry +  else +    raise e +  end +end + +def connection_string(database, host, netrc_file = nil) +  protocol  = "http" +  #hostname  = "127.0.0.1" +  port      = "5984" +  username  = "admin" +  password  = "" + +  netrc = File.read(netrc_file || '/etc/couchdb/couchdb.netrc') +  netrc.scan(/\w+ [\w\.]+/).each do |key_value| +    key, value = key_value.split ' ' +    case key +      when "machine"  then host ||= value + ':' + port +      when "login"    then username = value +      when "password" then password = value +    end +  end + +  host ||= '127.0.0.1:5984' + +  "%s://%s:%s@%s/%s" % [protocol, username, password, host, database] +end + +def usage(s) +  $stderr.puts(s) +  $stderr.puts("Usage: #{File.basename($0)} --host <host> --db <db> --id <doc_id> --data <json> [--file <file>] [--netrc-file <netrc-file>]") +  $stderr.puts("       #{File.basename($0)} --host <host> --db <db> --id <doc_id> --delete [--netrc-file <netrc-file>]") +  exit(2) +end + +main() diff --git a/puppet/modules/couchdb/files/local.ini b/puppet/modules/couchdb/files/local.ini new file mode 100644 index 00000000..7365b6c6 --- /dev/null +++ b/puppet/modules/couchdb/files/local.ini @@ -0,0 +1,84 @@ +; CouchDB Configuration Settings + +; Custom settings should be made in this file. They will override settings +; in default.ini, but unlike changes made to default.ini, this file won't be +; overwritten on server upgrade. + +[couchdb] +;max_document_size = 4294967296 ; bytes + +[httpd] +;port = 5984 +;bind_address = 127.0.0.1 +; Options for the MochiWeb HTTP server. +;server_options = [{backlog, 128}, {acceptor_pool_size, 16}] +; For more socket options, consult Erlang's module 'inet' man page. +;socket_options = [{recbuf, 262144}, {sndbuf, 262144}, {nodelay, true}] + +; Uncomment next line to trigger basic-auth popup on unauthorized requests. +;WWW-Authenticate = Basic realm="administrator" + +; Uncomment next line to set the configuration modification whitelist. Only +; whitelisted values may be changed via the /_config URLs. To allow the admin +; to change this value over HTTP, remember to include {httpd,config_whitelist} +; itself. Excluding it from the list would require editing this file to update +; the whitelist. +;config_whitelist = [{httpd,config_whitelist}, {log,level}, {etc,etc}] + +[httpd_global_handlers] +;_google = {couch_httpd_proxy, handle_proxy_req, <<"http://www.google.com">>} + +[couch_httpd_auth] +; If you set this to true, you should also uncomment the WWW-Authenticate line +; above. If you don't configure a WWW-Authenticate header, CouchDB will send +; Basic realm="server" in order to prevent you getting logged out. +; require_valid_user = false + +[log] +;level = debug + +[os_daemons] +; For any commands listed here, CouchDB will attempt to ensure that +; the process remains alive while CouchDB runs as well as shut them +; down when CouchDB exits. +;foo = /path/to/command -with args + +[daemons] +; enable SSL support by uncommenting the following line and supply the PEM's below. +; the default ssl port CouchDB listens on is 6984 +; httpsd = {couch_httpd, start_link, [https]} + +[ssl] +;cert_file = /full/path/to/server_cert.pem +;key_file = /full/path/to/server_key.pem +;password = somepassword +; set to true to validate peer certificates +verify_ssl_certificates = false +; Path to file containing PEM encoded CA certificates (trusted +; certificates used for verifying a peer certificate). May be omitted if +; you do not want to verify the peer. +;cacert_file = /full/path/to/cacertf +; The verification fun (optionnal) if not specidied, the default +; verification fun will be used. +;verify_fun = {Module, VerifyFun} +ssl_certificate_max_depth = 1 +; To enable Virtual Hosts in CouchDB, add a vhost = path directive. All requests to +; the Virual Host will be redirected to the path. In the example below all requests +; to http://example.com/ are redirected to /database. +; If you run CouchDB on a specific port, include the port number in the vhost: +; example.com:5984 = /database + +[vhosts] +;example.com = /database/ + +[update_notification] +;unique notifier name=/full/path/to/exe -with "cmd line arg" + +; To create an admin account uncomment the '[admins]' section below and add a +; line in the format 'username = password'. When you next start CouchDB, it +; will change the password to a hash (so that your passwords don't linger +; around in plain-text files). You can add more admin accounts with more +; 'username = password' lines. Don't forget to restart CouchDB after +; changing this. +[admins] +;admin = mysecretpassword diff --git a/puppet/modules/couchdb/lib/facter/couchdb_pwhash_alg.rb b/puppet/modules/couchdb/lib/facter/couchdb_pwhash_alg.rb new file mode 100644 index 00000000..60ae701a --- /dev/null +++ b/puppet/modules/couchdb/lib/facter/couchdb_pwhash_alg.rb @@ -0,0 +1,43 @@ +require 'facter' + +def version_parts ( version ) +  # gives back a hash containing major, minor and patch numbers +  # of a give version string + +  parts = Hash.new +  first, *rest = version.split(".") +  parts["major"] = first +  parts["minor"] = rest[0] +  parts["patch"] = rest[1] +  return parts +end + +def couchdb_pwhash_alg +  # couchdb uses sha1 as pw hash algorithm until v. 1.2, +  # but pbkdf2 from v.1.3 on. +  # see http://docs.couchdb.org/en/1.4.x/configuring.html for +  # details + +  couchdb_version = Facter.value(:couchdb_version) +  version = version_parts(couchdb_version) +  major = version["major"].to_i +  alg = case major +    when 0 then alg = 'n/a' +    when 1 then +      minor = version['minor'].to_i +      if minor < 3 +        alg = 'sha1' +      else +        alg = 'pbkdf2' +      end +  else +    alg = 'pbkdf2' +  end +  return alg +end + +Facter.add(:couchdb_pwhash_alg) do +  setcode do +    couchdb_pwhash_alg +  end +end diff --git a/puppet/modules/couchdb/lib/facter/couchdb_version.rb b/puppet/modules/couchdb/lib/facter/couchdb_version.rb new file mode 100644 index 00000000..3a721169 --- /dev/null +++ b/puppet/modules/couchdb/lib/facter/couchdb_version.rb @@ -0,0 +1,34 @@ +require 'facter' + +def deb_installed_version ( name ) +  # returns an empty string if package is not installed, +  # otherwise the version + +  version = `apt-cache policy #{name} | grep Installed 2>&1` +  version.slice! "  Installed: " +  version.slice! "(none)" +  return version.strip.chomp +end + +def couchdb_version +  bigcouch = deb_installed_version("bigcouch") +  if bigcouch.empty? +    couchdb = deb_installed_version("couchdb") +    if couchdb.empty? +      version = 'n/a' +    else +      version =  couchdb +    end +  else +    # bigcouch is currently only available in one version (0.4.2), +    # which includes couchdb 1.1.1 +    version = '1.1.1' +  end +  return version +end + +Facter.add(:couchdb_version) do +  setcode do +    couchdb_version +  end +end diff --git a/puppet/modules/couchdb/lib/puppet/parser/functions/couchdblookup.rb b/puppet/modules/couchdb/lib/puppet/parser/functions/couchdblookup.rb new file mode 100644 index 00000000..b9067d2a --- /dev/null +++ b/puppet/modules/couchdb/lib/puppet/parser/functions/couchdblookup.rb @@ -0,0 +1,55 @@ +# +# A basic function to retrieve data in couchdb +# + + +module Puppet::Parser::Functions +  newfunction(:couchdblookup, :type => :rvalue) do |args| +    require 'json' +    require 'open-uri' + +    raise Puppet::ParseError, ("couchdblookup(): wrong number of arguments (#{args.length}; must be 2 or 3)") unless args.length.between?(2, 3) + +    url = args[0] +    key = args[1] +    default = args[2] if args.length >= 3 + +    begin +      json = JSON.parse(open(URI.parse(url)).read) +    rescue OpenURI::HTTPError => error +      raise Puppet::ParseError, "couchdblookup(): fetching URL #{url} failed with status '#{error.message}'" +    rescue Timeout::Error => error +      raise Puppet::ParseError, "couchdblookup(): connection to couchdb server timed out: '#{error.message}'" +    rescue Errno::ECONNREFUSED => error +      raise Puppet::ParseError, "couchdblookup(): connection to couchdb server failed: '#{error.message}'" +    rescue JSON::ParserError => error +      raise Puppet::ParseError, "couchdblookup(): failed to parse JSON received from couchdb: '#{error.message}'" +    rescue StandardError => error +      raise Puppet::ParseError, "couchdblookup(): something unexpected happened: '#{error.inspect}'" +    end + +    result = nil + +    if json.has_key?("rows") + +      if json['rows'].length > 1 +        arr = json['rows'].collect do |x| +          x[key] if x.is_a?(Hash) and x.has_key?(key) +        end +        arr.compact! +        result = arr unless arr.empty? + +      elsif json['rows'].length == 1 +        hash = json['rows'].pop +        result = hash[key] if hash.is_a?(Hash) +      end + +    elsif json.has_key?(key) +      result = json[key] +    end + +    result or default or raise Puppet::ParseError, "couchdblookup(): key '#{key}' not found in JSON object !" + +  end +end + diff --git a/puppet/modules/couchdb/lib/puppet/parser/functions/pbkdf2.rb b/puppet/modules/couchdb/lib/puppet/parser/functions/pbkdf2.rb new file mode 100644 index 00000000..46400c9c --- /dev/null +++ b/puppet/modules/couchdb/lib/puppet/parser/functions/pbkdf2.rb @@ -0,0 +1,62 @@ +# +# pbkdf2.rb +# + +module Puppet::Parser::Functions +  newfunction(:pbkdf2, :type => :rvalue, :doc => <<-EOS +This converts a password and a salt (and optional iterations and keylength +parameters) to a hash containing the salted SHA1 password hash, salt, +iterations and keylength. +pbkdf2 is used i.e. for couchdb passwords since v1.3. + +Example usage: +  $pbkdf2 = pbkdf2($::couchdb::admin_pw, $::couchdb::admin_salt) +  $sha1   = $pbkdf2['sha1'] +EOS +  ) do |arguments| +    require 'openssl' +    require 'base64' + +    raise(Puppet::ParseError, "pbkdf2(): Wrong number of arguments " + +      "passed (#{arguments.size} but we require at least 2)") if arguments.size < 2 + +    unless arguments.is_a?(Array) +      raise(Puppet::ParseError, 'pbkdf2(): Requires a ' + +        "Array argument, you passed: #{password.class}") +    end + +    password   = arguments[0] +    salt       = arguments[1] + +    if arguments.size > 2 +      iterations = arguments[2].to_i +    else +      iterations = 1000 +    end + +    if arguments.size > 3 +      keylength  = arguments[3].to_i +    else +      keylength  = 20 +    end + +    pbkdf2 = OpenSSL::PKCS5::pbkdf2_hmac_sha1( +      password, +      salt, +      iterations, +      keylength +    ) + +    return_hash = Hash.new() +    # return hex encoded string +    return_hash['sha1']       = pbkdf2.unpack('H*')[0] +    return_hash['password']   = password +    return_hash['salt']       = salt +    return_hash['iterations'] = iterations +    return_hash['keylength']  = keylength + +    return return_hash +  end +end + +# vim: set ts=2 sw=2 et : diff --git a/puppet/modules/couchdb/manifests/add_user.pp b/puppet/modules/couchdb/manifests/add_user.pp new file mode 100644 index 00000000..29c6a8c8 --- /dev/null +++ b/puppet/modules/couchdb/manifests/add_user.pp @@ -0,0 +1,39 @@ +define couchdb::add_user ( $roles, $pw, $salt = '' ) { +  # Couchdb < 1.2 needs a pre-hashed pw and salt +  # If you provide a salt, couchdb::add_user will assume that +  # $pw is prehashed and pass both parameters to couchdb::update +  # If $salt is empty, couchdb::add_user will assume that the pw +  # is plaintext and will pass it to couchdb::update + +  if $::couchdb::bigcouch == true { +    $port = 5986 +  } else { +    $port = 5984 +  } + +  if $salt == '' { +    # unhashed, plaintext pw, no salt. For couchdb >= 1.2 +    $data = "{\"type\": \"user\", \"name\": \"${name}\", \"roles\": ${roles}, \"password\": \"${pw}\"}" +  } else { +    # prehashed pw with salt, for couchdb < 1.2 +    # salt and encrypt pw +    # str_and_salt2sha1 is a function from leap's stdlib module +    $pw_and_salt = [ $pw, $salt ] +    $sha         = str_and_salt2sha1($pw_and_salt) +    $data = "{\"type\": \"user\", \"name\": \"${name}\", \"roles\": ${roles}, \"password_sha\": \"${sha}\", \"salt\": \"${salt}\"}" +  } + +  # update the user with the given password unless they already work +  couchdb::document { "update_user_${name}": +    host   => "127.0.0.1:${port}", +    db     => '_users', +    id     => "org.couchdb.user:${name}", +    data   => $data +  } + +  couchdb::query::setup { $name: +    user  => $name, +    pw    => $pw, +  } + +} diff --git a/puppet/modules/couchdb/manifests/backup.pp b/puppet/modules/couchdb/manifests/backup.pp new file mode 100644 index 00000000..a477b5b1 --- /dev/null +++ b/puppet/modules/couchdb/manifests/backup.pp @@ -0,0 +1,51 @@ +# configure backup using couchdb-backup.py +class couchdb::backup { + +  include couchdb::params + +  # used in ERB templates +  $bind_address = $couchdb::params::bind_address +  $port         = $couchdb::params::port +  $backupdir    = $couchdb::params::backupdir + +  file { $couchdb::params::backupdir: +    ensure  => directory, +    mode    => '0755', +    require => Package['couchdb'], +  } + +  file { '/usr/local/sbin/couchdb-backup.py': +    ensure  => present, +    owner   => root, +    group   => root, +    mode    => '0755', +    content => template('couchdb/couchdb-backup.py.erb'), +    require => File[$couchdb::params::backupdir], +  } + +  cron { 'couchdb-backup': +    command => '/usr/local/sbin/couchdb-backup.py 2> /dev/null', +    hour    => 3, +    minute  => 0, +    require => File['/usr/local/sbin/couchdb-backup.py'], +  } + +  case $::operatingsystem { +    /Debian|Ubunu/: { +      # note: python-couchdb >= 0.8 required, which is found in debian wheezy. +      ensure_packages (['python-couchdb', 'python-simplejson'], { +        before => File['/usr/local/sbin/couchdb-backup.py'] +      }) +    } +    /RedHat|Centos/: { +      exec {'install python-couchdb using easy_install': +        command => 'easy_install http://pypi.python.org/packages/2.6/C/CouchDB/CouchDB-0.8-py2.6.egg', +        creates => '/usr/lib/python2.6/site-packages/CouchDB-0.8-py2.6.egg', +      } +    } +    default: { +      err('This module has not been written to support your operating system') +    } +  } + +} diff --git a/puppet/modules/couchdb/manifests/base.pp b/puppet/modules/couchdb/manifests/base.pp new file mode 100644 index 00000000..6c7bf25f --- /dev/null +++ b/puppet/modules/couchdb/manifests/base.pp @@ -0,0 +1,124 @@ +# configure couchdb +class couchdb::base { + +  if $::couchdb::bigcouch == true { +    $couchdb_user = 'bigcouch' +    include couchdb::bigcouch +  } else { +    $couchdb_user = 'couchdb' +  } + +  # we use package{} here because bigcouch.pp overwrites it and +  # this won't work with ensure_packages() +  package {'couchdb': +    ensure => installed +  } + +  service { 'couchdb': +    ensure    => running, +    hasstatus => true, +    enable    => true, +    require   => Package['couchdb'] +  } + +  # todo: make host/port configurable +  exec { 'wait_for_couchdb': +    command => 'wget --retry-connrefused --tries 10 --quiet "http://127.0.0.1:5984" -O /dev/null', +    require => Service['couchdb'] +  } + + +  # couchrest gem is required for couch-doc-update script, +  # and it needs the ruby-dev package installed to build + +  if versioncmp($::operatingsystemrelease, '8') < 0 { +    $couchrest_version = '1.2' +  } +  else { +    # couchrest v1.2.1 doesn't build with default debian jessie rake version +    # shipped as debian package (10.3.2) +    # see https://leap.se/code/issues/7754 +    $couchrest_version = '1.2.0' +  } + +  ensure_packages('ruby-dev') +  ensure_packages('couchrest', { +    provider => 'gem', +    ensure   => $couchrest_version, +    require  => Package['ruby-dev'] +  }) + +  File['/usr/local/bin/couch-doc-update'] ->  Couchdb::Update <| |> +  File['/usr/local/bin/couch-doc-diff'] ->  Couchdb::Update <| |> + +  Couchdb::Update <| |> -> Couchdb::Document <| |> + +  file { +    '/usr/local/bin/couch-doc-update': +      source  => 'puppet:///modules/couchdb/couch-doc-update', +      mode    => '0755', +      owner   => 'root', +      group   => 'root', +      require => Package['couchrest']; + +    '/usr/local/bin/couch-doc-diff': +      source  => 'puppet:///modules/couchdb/couch-doc-diff', +      mode    => '0755', +      owner   => 'root', +      group   => 'root', +      require => Package['couchrest']; + +    '/etc/couchdb/local.ini': +      source  => [ "puppet:///modules/site_couchdb/${::fqdn}/local.ini", +                  'puppet:///modules/site_couchdb/local.ini', +                  'puppet:///modules/couchdb/local.ini' ], +      notify  => Service[couchdb], +      owner   => $couchdb_user, +      group   => $couchdb_user, +      mode    => '0660', +      require => Package['couchdb']; + +    '/etc/couchdb/local.d': +      ensure  => directory, +      require => Package['couchdb']; +  } + +  $alg  = $::couchdb::pwhash_alg +  $salt = $::couchdb::admin_salt +  case $alg { +    'sha1': { +      # str_and_salt2sha1 is a function from leap's stdlib module +      $pw_and_salt = [ $::couchdb::admin_pw, $salt ] +      $sha1        = str_and_salt2sha1($pw_and_salt) +      $admin_hash  = "-hashed-${sha1},${salt}" +    } +    'pbkdf2': { +      $pbkdf2      = pbkdf2($::couchdb::admin_pw, $::couchdb::admin_salt, 10) +      $sha1        = $pbkdf2['sha1'] +      $admin_hash  = "-pbkdf2-${sha1},${salt},10" +    } +    default:  { fail ("Unknown fact couchdb_pwhash_alg ${::couchdb_pwhash_alg} - Exiting.") } +  } + +  file { '/etc/couchdb/local.d/admin.ini': +    content => template('couchdb/admin.ini.erb'), +    mode    => '0600', +    owner   => $couchdb_user, +    group   => $couchdb_user, +    notify  => Service[couchdb], +    require => File['/etc/couchdb/local.d']; +  } + +  case $::couchdb::bigcouch { +    true: { $restart_command = '/etc/init.d/bigcouch restart; sleep 6' } +    default: { $restart_command = '/etc/init.d/couchdb restart; sleep 6' } +  } + +  exec { 'couchdb_restart': +    command     => $restart_command, +    path        => ['/bin', '/usr/bin',], +    subscribe   => File['/etc/couchdb/local.d/admin.ini', +                        '/etc/couchdb/local.ini'], +    refreshonly => true +  } +} diff --git a/puppet/modules/couchdb/manifests/bigcouch.pp b/puppet/modules/couchdb/manifests/bigcouch.pp new file mode 100644 index 00000000..a97411bf --- /dev/null +++ b/puppet/modules/couchdb/manifests/bigcouch.pp @@ -0,0 +1,51 @@ +class couchdb::bigcouch inherits couchdb::base { + +  file { +    '/opt/bigcouch': +      ensure => directory, +      mode   => '0755'; + +    '/etc/couchdb': +      ensure => directory, +      mode   => '0755', +      before => Package['couchdb']; + +    '/opt/bigcouch/etc': +      ensure => link, +      target => '/etc/couchdb', +      before => Package['couchdb']; +  } + +  # there's no bigcouch in the official debian repo, you need +  # to setup a repository for that. You can use class +  # couchdb::bigcouch::package::cloudant for unauthenticated 0.4.0 packages, +  # or site_apt::leap_repo from the leap_platfrom repository +  # for signed 0.4.2 packages + +  Package['couchdb'] { +    name    => 'bigcouch' +  } + +  file { '/opt/bigcouch/etc/vm.args': +    content => template('couchdb/bigcouch/vm.args'), +    mode    => '0640', +    owner   => 'bigcouch', +    group   => 'bigcouch', +    require => Package['couchdb'], +    notify  => Service[couchdb] +  } + +  file { '/opt/bigcouch/etc/default.ini': +    content => template('couchdb/bigcouch/default.ini'), +    mode    => '0640', +    owner   => 'bigcouch', +    group   => 'bigcouch', +    require => Package['couchdb'], +    notify  => Service[couchdb] +  } + +  Service['couchdb'] { +    name     => 'bigcouch' +  } + +} diff --git a/puppet/modules/couchdb/manifests/bigcouch/add_node.pp b/puppet/modules/couchdb/manifests/bigcouch/add_node.pp new file mode 100644 index 00000000..ed9db94b --- /dev/null +++ b/puppet/modules/couchdb/manifests/bigcouch/add_node.pp @@ -0,0 +1,8 @@ +define couchdb::bigcouch::add_node { + +  couchdb::bigcouch::document { "add_${name}": +    db   => 'nodes', +    id   => "bigcouch@${name}", +    ensure => 'present' +  } +} diff --git a/puppet/modules/couchdb/manifests/bigcouch/debian.pp b/puppet/modules/couchdb/manifests/bigcouch/debian.pp new file mode 100644 index 00000000..645c6da8 --- /dev/null +++ b/puppet/modules/couchdb/manifests/bigcouch/debian.pp @@ -0,0 +1,11 @@ +class couchdb::bigcouch::debian inherits couchdb::debian { + +  File['/etc/init.d/couchdb'] { +    ensure => absent +  } + +  file {'/etc/init.d/bigcouch': +    ensure => link, +    target => '/usr/bin/sv' +  } +} diff --git a/puppet/modules/couchdb/manifests/bigcouch/document.pp b/puppet/modules/couchdb/manifests/bigcouch/document.pp new file mode 100644 index 00000000..13f4ac17 --- /dev/null +++ b/puppet/modules/couchdb/manifests/bigcouch/document.pp @@ -0,0 +1,14 @@ +define couchdb::bigcouch::document ( +  $db, +  $id, +  $host = '127.0.0.1:5986', +  $data ='{}', +  $ensure ='content') { +  couchdb::document { $name: +    ensure => $ensure, +    host   => $host, +    db     => $db, +    id     => $id, +    data   => $data +  } +} diff --git a/puppet/modules/couchdb/manifests/bigcouch/package/cloudant.pp b/puppet/modules/couchdb/manifests/bigcouch/package/cloudant.pp new file mode 100644 index 00000000..cfdcf10c --- /dev/null +++ b/puppet/modules/couchdb/manifests/bigcouch/package/cloudant.pp @@ -0,0 +1,35 @@ +class couchdb::bigcouch::package::cloudant ( +  $ensure = 'present' +) { + +  # cloudant's signing key can be fetched from +  # http://packages.cloudant.com/KEYS, please use the apt module to +  # distribute it on your servers after verifying its fingerprint + +  # cloudant's wheezy repo will fail cause in their Release file +  # (http://packages.cloudant.com/debian/dists/wheezy/Release) they +  # wrongly marked the packages for squeeze +  # so we will use their squeeze repo here +  apt::sources_list {'bigcouch-cloudant.list': +    ensure  => $ensure, +    content => 'deb http://packages.cloudant.com/debian squeeze main' +  } + +  # right now, cloudant only provides authenticated bigcouch 0.4.2 packages +  # for squeeze, therefore we need to allow the installation of the depending +  # packages libicu44 and libssl0.9.8 from squeeze + +  if $::lsbdistcodename == 'wheezy' { +    apt::sources_list {'squeeze.list': +      ensure  => $ensure, +      content => 'deb http://http.debian.net/debian squeeze main +deb http://security.debian.org/ squeeze/updates main +'   } +    apt::preferences_snippet { 'bigcouch_squeeze_deps': +      ensure   => $ensure, +      package  => 'libicu44 libssl0.9.8', +      priority => '980', +      pin      => 'release o=Debian,n=squeeze' +    } +  } +} diff --git a/puppet/modules/couchdb/manifests/create_db.pp b/puppet/modules/couchdb/manifests/create_db.pp new file mode 100644 index 00000000..8a8d1144 --- /dev/null +++ b/puppet/modules/couchdb/manifests/create_db.pp @@ -0,0 +1,21 @@ +define couchdb::create_db ( +  $host='127.0.0.1:5984', +  $admins="{\"names\": [], \"roles\": [] }", +  $members="{\"names\": [], \"roles\": [] }" ) +{ + +  couchdb::query { "create_db_${name}": +    cmd    => 'PUT', +    host   => $host, +    path   => $name, +    unless => "/usr/bin/curl -s -f --netrc-file /etc/couchdb/couchdb.netrc ${host}/${name}" +  } + +  couchdb::document { "${name}_security": +    db   => $name, +    id   => '_security', +    host => $host, +    data => "{ \"admins\": ${admins}, \"members\": ${members} }", +    require => Couchdb::Query["create_db_${name}"] +  } +} diff --git a/puppet/modules/couchdb/manifests/debian.pp b/puppet/modules/couchdb/manifests/debian.pp new file mode 100644 index 00000000..b83b227a --- /dev/null +++ b/puppet/modules/couchdb/manifests/debian.pp @@ -0,0 +1,15 @@ +# installs initscript and dependent packages on debian +class couchdb::debian inherits couchdb::base { + +  ensure_packages('libjs-jquery') + +  file { '/etc/init.d/couchdb': +    source  => [ +      'puppet:///modules/site_couchdb/Debian/couchdb', +      'puppet:///modules/couchdb/Debian/couchdb' ], +    mode    => '0755', +    owner   => 'root', +    group   => 'root', +    require => Package['couchdb'] +  } +} diff --git a/puppet/modules/couchdb/manifests/deploy_config.pp b/puppet/modules/couchdb/manifests/deploy_config.pp new file mode 100644 index 00000000..2ce1fd20 --- /dev/null +++ b/puppet/modules/couchdb/manifests/deploy_config.pp @@ -0,0 +1,12 @@ +class couchdb::deploy_config { + +  file { '/etc/couchdb/local.ini': +    source  => [ "puppet:///modules/site_couchdb/${::fqdn}/local.ini", +                'puppet:///modules/site_couchdb/local.ini', +                'puppet:///modules/couchdb/local.ini' ], +    notify  => Service[couchdb], +    owner   => couchdb, +    group   => couchdb, +    mode    => '0660' +  } +} diff --git a/puppet/modules/couchdb/manifests/document.pp b/puppet/modules/couchdb/manifests/document.pp new file mode 100644 index 00000000..6180474b --- /dev/null +++ b/puppet/modules/couchdb/manifests/document.pp @@ -0,0 +1,47 @@ +# Usage: +# couchdb::document { id: +#   db => "database", +#   data => "content", +#   ensure => {absent,present,*content*} +# } +# +define couchdb::document( +  $db, +  $id, +  $host   = '127.0.0.1:5984', +  $data   = '{}', +  $netrc  = '/etc/couchdb/couchdb.netrc', +  $ensure = 'content') { + +  $url = "${host}/${db}/${id}" + +  case $ensure { +    default: { err ( "unknown ensure value '${ensure}'" ) } +    content: { +      exec { "couch-doc-update --netrc-file ${netrc} --host ${host} --db ${db} --id ${id} --data \'${data}\'": +        require => Exec['wait_for_couchdb'], +        unless  => "couch-doc-diff $url '$data'" +      } +    } + +    present: { +      couchdb::query { "create_${db}_${id}": +        cmd    => 'PUT', +        host   => $host, +        path   => "${db}/${id}", +        require => Exec['wait_for_couchdb'], +        unless => "/usr/bin/curl -s -f --netrc-file ${netrc} ${url}" +      } +    } + +    absent: { +      couchdb::query { "destroy_${db}_${id}": +        cmd    => 'DELETE', +        host   => $host, +        path   => "${db}/${id}", +        require => Exec['wait_for_couchdb'], +        unless => "/usr/bin/curl -s -f --netrc-file ${netrc} ${url}" +      } +    } +  } +} diff --git a/puppet/modules/couchdb/manifests/init.pp b/puppet/modules/couchdb/manifests/init.pp new file mode 100644 index 00000000..12598ba0 --- /dev/null +++ b/puppet/modules/couchdb/manifests/init.pp @@ -0,0 +1,31 @@ +# initial couchdb class +class couchdb ( +  $admin_pw, +  $admin_salt = '', +  $bigcouch = false, +  $bigcouch_cookie = '', +  $ednp_port = '9001', +  $chttpd_bind_address = '0.0.0.0', +  $pwhash_alg = 'pbkdf2' ) +{ + +  # stdlib is needed i.e. for ensure_packages() +  include ::stdlib + +  case $::operatingsystem { +    Debian: { +      case $::lsbdistcodename { +        /lenny|squeeze|wheezy|jessie/: { +          include couchdb::debian +          if $bigcouch == true { +            include couchdb::bigcouch::debian +          } +        } +        default:         { fail "couchdb not available for ${::operatingsystem}/${::lsbdistcodename}" } +      } +    } +    RedHat: { include couchdb::redhat } +  } + +  ensure_packages('curl') +} diff --git a/puppet/modules/couchdb/manifests/mirror_db.pp b/puppet/modules/couchdb/manifests/mirror_db.pp new file mode 100644 index 00000000..b07b6749 --- /dev/null +++ b/puppet/modules/couchdb/manifests/mirror_db.pp @@ -0,0 +1,21 @@ +define couchdb::mirror_db ( +  $host='127.0.0.1:5984', +  $from='', +  $to='', +  $user='replication', +  $role='replication' +  ) +{ +  $source = "${from}/${name}" +  if $to == '' { $target = $name } +  else { $target = "${to}/${name}" } + +  couchdb::document { "${name}_replication": +    db      => "_replicator", +    id      => "${name}_replication", +    netrc   => "/etc/couchdb/couchdb-${user}.netrc", +    host    => $host, +    data    => "{ \"source\": \"${source}\", \"target\": \"${target}\", \"continuous\": true, \"user_ctx\": { \"name\": \"${user}\", \"roles\": [\"${role}\"] }, \"owner\": \"${user}\" }", +    require => Couchdb::Query["create_db_${name}"] +  } +} diff --git a/puppet/modules/couchdb/manifests/params.pp b/puppet/modules/couchdb/manifests/params.pp new file mode 100644 index 00000000..02d5f02e --- /dev/null +++ b/puppet/modules/couchdb/manifests/params.pp @@ -0,0 +1,23 @@ +class couchdb::params { + +  $bind_address = $::couchdb_bind_address ? { +    ''      => '127.0.0.1', +    default => $::couchdb_bind_address, +  } + +  $port = $::couchdb_port ? { +    ''      => '5984', +    default => $::couchdb_port, +  } + +  $backupdir = $::couchdb_backupdir ? { +    ''      => '/var/backups/couchdb', +    default => $::couchdb_backupdir, +  } + +  $cert_path = $::couchdb_cert_path ? { +    ""      => '/etc/couchdb', +    default => $::couchdb_cert_path, +  } + +} diff --git a/puppet/modules/couchdb/manifests/query.pp b/puppet/modules/couchdb/manifests/query.pp new file mode 100644 index 00000000..9507ca1e --- /dev/null +++ b/puppet/modules/couchdb/manifests/query.pp @@ -0,0 +1,12 @@ +define couchdb::query ( +  $cmd, $path, +  $netrc='/etc/couchdb/couchdb.netrc', +  $host='127.0.0.1:5984', +  $data = '{}', +  $unless = undef) { + +  exec { "/usr/bin/curl -s --netrc-file ${netrc} -X ${cmd} ${host}/${path} --data \'${data}\'": +    require => [ Package['curl'], Exec['wait_for_couchdb'] ], +    unless  => $unless +  } +} diff --git a/puppet/modules/couchdb/manifests/query/setup.pp b/puppet/modules/couchdb/manifests/query/setup.pp new file mode 100644 index 00000000..451eb536 --- /dev/null +++ b/puppet/modules/couchdb/manifests/query/setup.pp @@ -0,0 +1,10 @@ +define couchdb::query::setup ($user, $pw, $host='127.0.0.1') { + +  file { "/etc/couchdb/couchdb-${user}.netrc": +    content => "machine ${host} login ${user} password ${pw}", +    mode    => '0600', +    owner   => $::couchdb::base::couchdb_user, +    group   => $::couchdb::base::couchdb_user, +    require => Package['couchdb']; +  } +} diff --git a/puppet/modules/couchdb/manifests/redhat.pp b/puppet/modules/couchdb/manifests/redhat.pp new file mode 100644 index 00000000..defa0a94 --- /dev/null +++ b/puppet/modules/couchdb/manifests/redhat.pp @@ -0,0 +1 @@ +class couchdb::redhat inherits couchdb::base {} diff --git a/puppet/modules/couchdb/manifests/ssl/deploy_cert.pp b/puppet/modules/couchdb/manifests/ssl/deploy_cert.pp new file mode 100644 index 00000000..d3e743f1 --- /dev/null +++ b/puppet/modules/couchdb/manifests/ssl/deploy_cert.pp @@ -0,0 +1,28 @@ +define couchdb::ssl::deploy_cert ($cert, $key) { + +  include couchdb::params + +  file { 'couchdb_cert_directory': +    ensure  => 'directory', +    path    => $couchdb::params::cert_path, +    mode    => '0600', +    owner   => 'couchdb', +    group   => 'couchdb'; +  } + +  file { 'couchdb_cert': +    path    => "${couchdb::params::cert_path}/server_cert.pem", +    mode    => '0644', +    owner   => 'couchdb', +    group   => 'couchdb', +    content => $cert +  } + +  file { 'couchdb_key': +    path    => "${couchdb::params::cert_path}/server_key.pem", +    mode    => '0600', +    owner   => 'couchdb', +    group   => 'couchdb', +    content => $key +  } +} diff --git a/puppet/modules/couchdb/manifests/ssl/generate_cert.pp b/puppet/modules/couchdb/manifests/ssl/generate_cert.pp new file mode 100644 index 00000000..a443250e --- /dev/null +++ b/puppet/modules/couchdb/manifests/ssl/generate_cert.pp @@ -0,0 +1,25 @@ +# configures cert for ssl access +class couchdb::ssl::generate_cert { + +  ensure_packages('openssl') + +  file { $couchdb::cert_path: +    ensure => 'directory', +    mode   => '0600', +    owner  => 'couchdb', +    group  => 'couchdb'; +  } + +exec { 'generate-certs': +    command => "/usr/bin/openssl req -new -inform PEM -x509 -nodes -days 150 -subj \ +'/C=ZZ/ST=AutoSign/O=AutoSign/localityName=AutoSign/commonName=${::hostname}/organizationalUnitName=AutoSign/emailAddress=AutoSign/' \ +-newkey rsa:2048 -out ${couchdb::cert_path}/couchdb_cert.pem -keyout ${couchdb::cert_path}/couchdb_key.pem", +    unless  => "/usr/bin/test -f ${couchdb::cert_path}/couchdb_cert.pem && +/usr/bin/test -f ${couchdb::params::cert_path}/couchdb_key.pem", +    require => [ +      File[$couchdb::params::cert_path], +      Exec['make-install'] +    ], +    notify  => Service['couchdb'], +  } +} diff --git a/puppet/modules/couchdb/manifests/update.pp b/puppet/modules/couchdb/manifests/update.pp new file mode 100644 index 00000000..b1dba84c --- /dev/null +++ b/puppet/modules/couchdb/manifests/update.pp @@ -0,0 +1,12 @@ +define couchdb::update ( +  $db, +  $id, +  $data, +  $host='127.0.0.1:5984', +  $unless=undef) { + +  exec { "couch-doc-update --host ${host} --db ${db} --id ${id} --data \'${data}\'": +    require => Exec['wait_for_couchdb'], +    unless  => $unless +  } +} diff --git a/puppet/modules/couchdb/spec/classes/couchdb_spec.rb b/puppet/modules/couchdb/spec/classes/couchdb_spec.rb new file mode 100644 index 00000000..e8e4174e --- /dev/null +++ b/puppet/modules/couchdb/spec/classes/couchdb_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe 'couchdb' do +  context 'given it is a wheezy system' do +    let(:params) { {:admin_pw => 'foo'} } +    let(:facts) do +      { +      :operatingsystemrelease => '7', +      :operatingsystem           => 'Debian', +      :lsbdistcodename           => 'wheezy', +      } +    end +    it "should install couchrest 1.2" do +      should contain_package('couchrest').with({ +        'ensure'=> '1.2', +      }) +    end +  end +  context 'given it is a jessie system' do +    let(:params) { {:admin_pw => 'foo'} } +    let(:facts) do +      { +      :operatingsystemrelease => '8', +      :operatingsystem           => 'Debian', +      :lsbdistcodename           => 'jessie', +      } +    end +    it "should install latest couchrest version" do +      should contain_package('couchrest').with({ +        'ensure'=> 'latest', +      }) +    end +  end +end + diff --git a/puppet/modules/couchdb/spec/fixtures/manifests/site.pp b/puppet/modules/couchdb/spec/fixtures/manifests/site.pp new file mode 100644 index 00000000..a959fb77 --- /dev/null +++ b/puppet/modules/couchdb/spec/fixtures/manifests/site.pp @@ -0,0 +1,8 @@ +# set a default exec path +# the logoutput exec parameter defaults to "on_error" in puppet 3, +# but to "false" in puppet 2.7, so we need to set this globally here +Exec { +  logoutput => on_failure, +  path    => '/usr/bin:/usr/sbin/:/bin:/sbin:/usr/local/bin:/usr/local/sbin' +} + diff --git a/puppet/modules/couchdb/spec/functions/versioncmp_spec.rb b/puppet/modules/couchdb/spec/functions/versioncmp_spec.rb new file mode 100644 index 00000000..0a244275 --- /dev/null +++ b/puppet/modules/couchdb/spec/functions/versioncmp_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +describe 'versioncmp' do +    it { should run.with_params('7.2','8').and_return(-1) } +    it { should run.with_params('7','8').and_return(-1) } +    it { should run.with_params('8','8').and_return(0) } +    it { should run.with_params('8.1','8').and_return(1) } +end + diff --git a/puppet/modules/couchdb/spec/spec_helper.rb b/puppet/modules/couchdb/spec/spec_helper.rb new file mode 100644 index 00000000..b55ede81 --- /dev/null +++ b/puppet/modules/couchdb/spec/spec_helper.rb @@ -0,0 +1,9 @@ +require 'rspec-puppet' + +fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures')) + +RSpec.configure do |c| +  c.module_path = File.join(fixture_path, 'modules') +  c.manifest_dir = File.join(fixture_path, 'manifests') +  c.environmentpath = File.join(Dir.pwd, 'spec') +end diff --git a/puppet/modules/couchdb/templates/admin.ini.erb b/puppet/modules/couchdb/templates/admin.ini.erb new file mode 100644 index 00000000..479f8bfc --- /dev/null +++ b/puppet/modules/couchdb/templates/admin.ini.erb @@ -0,0 +1,9 @@ +<%- require 'digest' -%> +[admins] +admin = <%= @admin_hash %> + +[couchdb] +<%- # uuid uniquely identifies this couchdb instance. if not set, couchdb will set a random one +    # but we want a stable one so that this config file doesn't change all the time. +    # Md5 of hostname and ipaddress seems reasonable, but it could be based on anything. -%> +uuid = <%= Digest::MD5.hexdigest(Facter.value("hostname") + Facter.value("ipaddress")) %> diff --git a/puppet/modules/couchdb/templates/bigcouch/default.ini b/puppet/modules/couchdb/templates/bigcouch/default.ini new file mode 100644 index 00000000..a315ddab --- /dev/null +++ b/puppet/modules/couchdb/templates/bigcouch/default.ini @@ -0,0 +1,172 @@ +[couchdb] +database_dir = /opt/bigcouch/var/lib +view_index_dir = /opt/bigcouch/var/lib +max_document_size = 67108864 +os_process_timeout = 5000 +max_dbs_open = 500 +delayed_commits = false + +[cluster] +; Default number of shards for a new database +q = 8 +; Default number of copies of each shard +n = 3 + +[chttpd] +port = 5984 +docroot = /opt/bigcouch/share/www + +; Options for the MochiWeb HTTP server. +;server_options = [{backlog, 128}, {acceptor_pool_size, 16}] + +; For more socket options, consult Erlang's module 'inet' man page. +;socket_options = [{recbuf, 262144}, {sndbuf, 262144}, {nodelay, true}] + +bind_address = <%= scope.lookupvar('couchdb::chttpd_bind_address') %> + +[chttps] +port = 6984 + +; cert_file = /full/path/to/server_cert.pem +; key_file = /full/path/to/server_key.pem +; password = somepassword +; also remember to enable the chttps daemon in [daemons] section. + +; set to true to validate peer certificates +verify_ssl_certificates = false + +; Path to file containing PEM encoded CA certificates (trusted +; certificates used for verifying a peer certificate). May be omitted if +; you do not want to verify the peer. +;cacert_file = /full/path/to/cacertf + +; The verification fun (optional) if not specified, the default +; verification fun will be used. +;verify_fun = {Module, VerifyFun} +ssl_certificate_max_depth = 1 + +[httpd] +port = 5986 +bind_address = 127.0.0.1 +authentication_handlers = {couch_httpd_oauth, oauth_authentication_handler}, {couch_httpd_auth, cookie_authentication_handler}, {couch_httpd_auth, default_authentication_handler} +default_handler = {couch_httpd_db, handle_request} +secure_rewrites = true +vhost_global_handlers = _utils, _uuids, _session, _oauth, _users +allow_jsonp = false +log_max_chunk_size = 1000000 + +[ssl] +port = 6984 + +[log] +file = /opt/bigcouch/var/log/bigcouch.log +level = info +include_sasl = true + +[couch_httpd_auth] +authentication_db = _users +authentication_redirect = /_utils/session.html +require_valid_user = false +timeout = 43200 ; (default to 12 hours) number of seconds before automatic logout +auth_cache_size = 50 ; size is number of cache entries + +[query_servers] +javascript = /opt/bigcouch/bin/couchjs /opt/bigcouch/share/couchjs/main.js + +[query_server_config] +reduce_limit = true +os_process_soft_limit = 100 + +[daemons] +view_manager={couch_view, start_link, []} +external_manager={couch_external_manager, start_link, []} +query_servers={couch_proc_manager, start_link, []} +httpd={couch_httpd, start_link, []} +stats_aggregator={couch_stats_aggregator, start, []} +stats_collector={couch_stats_collector, start, []} +uuids={couch_uuids, start, []} +auth_cache={couch_auth_cache, start_link, []} +replication_manager={couch_replication_manager, start_link, []} +vhosts={couch_httpd_vhost, start_link, []} +os_daemons={couch_os_daemons, start_link, []} +; Uncomment next line to enable SSL daemon +; chttpsd = {chttpd, start_link, [https]} + +[httpd_global_handlers] +/ = {couch_httpd_misc_handlers, handle_welcome_req, <<"Welcome">>} +favicon.ico = {couch_httpd_misc_handlers, handle_favicon_req, "/opt/bigcouch/share/www"} + +_utils = {couch_httpd_misc_handlers, handle_utils_dir_req, "/opt/bigcouch/share/www"} +_all_dbs = {couch_httpd_misc_handlers, handle_all_dbs_req} +_active_tasks = {couch_httpd_misc_handlers, handle_task_status_req} +_config = {couch_httpd_misc_handlers, handle_config_req} +_replicate = {couch_httpd_misc_handlers, handle_replicate_req} +_uuids = {couch_httpd_misc_handlers, handle_uuids_req} +_restart = {couch_httpd_misc_handlers, handle_restart_req} +_stats = {couch_httpd_stats_handlers, handle_stats_req} +_log = {couch_httpd_misc_handlers, handle_log_req} +_session = {couch_httpd_auth, handle_session_req} +_oauth = {couch_httpd_oauth, handle_oauth_req} +_system = {chttpd_misc, handle_system_req} + +[httpd_db_handlers] +_view_cleanup = {couch_httpd_db, handle_view_cleanup_req} +_compact = {couch_httpd_db, handle_compact_req} +_design = {couch_httpd_db, handle_design_req} +_temp_view = {couch_httpd_view, handle_temp_view_req} +_changes = {couch_httpd_db, handle_changes_req} + +[httpd_design_handlers] +_view = {couch_httpd_view, handle_view_req} +_show = {couch_httpd_show, handle_doc_show_req} +_list = {couch_httpd_show, handle_view_list_req} +_info = {couch_httpd_db,   handle_design_info_req} +_rewrite = {couch_httpd_rewrite, handle_rewrite_req} +_update = {couch_httpd_show, handle_doc_update_req} + +; enable external as an httpd handler, then link it with commands here. +; note, this api is still under consideration. +; [external] +; mykey = /path/to/mycommand + +; Here you can setup commands for CouchDB to manage +; while it is alive. It will attempt to keep each command +; alive if it exits. +; [os_daemons] +; some_daemon_name = /path/to/script -with args + + +[uuids] +; Known algorithms: +;   random - 128 bits of random awesome +;     All awesome, all the time. +;   sequential - monotonically increasing ids with random increments +;     First 26 hex characters are random. Last 6 increment in +;     random amounts until an overflow occurs. On overflow, the +;     random prefix is regenerated and the process starts over. +;   utc_random - Time since Jan 1, 1970 UTC with microseconds +;     First 14 characters are the time in hex. Last 18 are random. +algorithm = sequential + +[stats] +; rate is in milliseconds +rate = 1000 +; sample intervals are in seconds +samples = [0, 60, 300, 900] + +[attachments] +compression_level = 8 ; from 1 (lowest, fastest) to 9 (highest, slowest), 0 to disable compression +compressible_types = text/*, application/javascript, application/json, application/xml + +[replicator] +db = _replicator +; Maximum replicaton retry count can be a non-negative integer or "infinity". +max_replication_retry_count = 10 +max_http_sessions = 20 +max_http_pipeline_size = 50 +; set to true to validate peer certificates +verify_ssl_certificates = false +; file containing a list of peer trusted certificates (PEM format) +; ssl_trusted_certificates_file = /etc/ssl/certs/ca-certificates.crt +; maximum peer certificate depth (must be set even if certificate validation is off) +ssl_certificate_max_depth = 3 diff --git a/puppet/modules/couchdb/templates/bigcouch/vm.args b/puppet/modules/couchdb/templates/bigcouch/vm.args new file mode 100644 index 00000000..4618a52c --- /dev/null +++ b/puppet/modules/couchdb/templates/bigcouch/vm.args @@ -0,0 +1,32 @@ +# Each node in the system must have a unique name.  A name can be short +# (specified using -sname) or it can by fully qualified (-name).  There can be +# no communication between nodes running with the -sname flag and those running  +# with the -name flag. +-name bigcouch  + +# All nodes must share the same magic cookie for distributed Erlang to work. +# Comment out this line if you synchronized the cookies by other means (using +# the ~/.erlang.cookie file, for example). +-setcookie <%= scope.lookupvar('couchdb::bigcouch_cookie') %> + +# Tell SASL not to log progress reports +-sasl errlog_type error + +# Use kernel poll functionality if supported by emulator ++K true + +# Start a pool of asynchronous IO threads ++A 16 + +# Comment this line out to enable the interactive Erlang shell on startup ++Bd -noinput + +# read config files +# otherwise /etc/couchdb/local.d/admin.ini wouldn't be read mysteriously +-couch_ini /etc/couchdb/default.ini /etc/couchdb/local.ini /etc/couchdb/local.d/admin.ini /etc/couchdb/default.ini /etc/couchdb/local.ini /etc/couchdb/local.d/admin.ini +# + +# make firewalling easier, see +# http://stackoverflow.com/questions/8459949/bigcouch-cluster-connection-issue#comment10467603_8463814 + +-kernel inet_dist_listen_min <%= scope.lookupvar('couchdb::ednp_port') %> inet_dist_use_interface "{127,0,0,1}" diff --git a/puppet/modules/couchdb/templates/couchdb-backup.py.erb b/puppet/modules/couchdb/templates/couchdb-backup.py.erb new file mode 100644 index 00000000..c49df65b --- /dev/null +++ b/puppet/modules/couchdb/templates/couchdb-backup.py.erb @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# file manage by puppet  + +import os +import gzip +import tarfile +import datetime +import urllib2 +import simplejson +import couchdb.tools.dump +from os.path import join + +DB_URL="http://127.0.0.1:5984" +DUMP_DIR="<%= backupdir %>" +TODAY=datetime.datetime.today().strftime("%A").lower() + +ftar = os.path.join(DUMP_DIR,"%s.tar" % TODAY) +tmp_ftar = os.path.join(DUMP_DIR,"_%s.tar" % TODAY) +tar = tarfile.open(tmp_ftar, "w") + +databases = simplejson.load(urllib2.urlopen("%s/_all_dbs" % DB_URL)) + +for db in databases: +  db_file = os.path.join(DUMP_DIR,"%s.gz" % db) +  f = gzip.open(db_file, 'wb') +  couchdb.tools.dump.dump_db(os.path.join(DB_URL,db), output=f) +  f.close() +  tar.add(db_file,"%s.gz" % db) +  os.remove(db_file) + +tar.close() +os.rename(tmp_ftar,ftar) diff --git a/puppet/modules/git/files/config/CentOS/git-daemon b/puppet/modules/git/files/config/CentOS/git-daemon new file mode 100644 index 00000000..a9b208c2 --- /dev/null +++ b/puppet/modules/git/files/config/CentOS/git-daemon @@ -0,0 +1,26 @@ +# git-daemon config file + +# location of the lockfile +#LOCKFILE=/var/lock/subsys/git-daemon + +# which directory to server +#GITDIR=/srv/git + +# do we serve vhosts? +# setting this to yes assumes that you  +# have in $GITDIR per vhost to serve +# a subdirectory containing their repos. +# for example: +# - /srv/git/git.example.com +# - /srv/git/git.example.org +#GITVHOST=no + +# the user git-daemon should run with +#GITUSER=nobody + +# options for the daemon +#OPTIONS="--reuseaddr --verbose --detach" + +# location of the daemon +#GITDAEMON=/usr/bin/git-daemon + diff --git a/puppet/modules/git/files/config/CentOS/git-daemon.vhosts b/puppet/modules/git/files/config/CentOS/git-daemon.vhosts new file mode 100644 index 00000000..62bb9d4b --- /dev/null +++ b/puppet/modules/git/files/config/CentOS/git-daemon.vhosts @@ -0,0 +1,27 @@ +# git-daemon config file + +# location of the lockfile +#LOCKFILE=/var/lock/subsys/git-daemon + +# which directory to server +#GITDIR=/srv/git + +# do we serve vhosts? +# setting this to yes assumes that you  +# have in $GITDIR per vhost to serve +# a subdirectory containing their repos. +# for example: +# - /srv/git/git.example.com +# - /srv/git/git.example.org +#GITVHOST=no +GITVHOST=yes + +# the user git-daemon should run with +#GITUSER=nobody + +# options for the daemon +#OPTIONS="--reuseaddr --verbose --detach" + +# location of the daemon +#GITDAEMON=/usr/bin/git-daemon + diff --git a/puppet/modules/git/files/config/Debian/git-daemon b/puppet/modules/git/files/config/Debian/git-daemon new file mode 100644 index 00000000..b25e1e7f --- /dev/null +++ b/puppet/modules/git/files/config/Debian/git-daemon @@ -0,0 +1,22 @@ +# Defaults for the git-daemon initscript + +# Set to yes to start git-daemon +RUN=yes + +# Set to the user and group git-daemon should run as +USER=nobody +GROUP=nogroup + +# Set the base path and the directory where the repositories are. +REPOSITORIES="/srv/git" + +# Provide a way to have custom setup. +# +# Note, when ADVANCED_OPTS is defined the REPOSITORIES setting is ignored, +# so take good care to specify exactly what git-daemon have to do. +# +# Here is an example from the man page: +#ADVANCED_OPTS="--verbose --export-all \ +#               --interpolated-path=/pub/%IP/%D \ +#               /pub/192.168.1.200/software \ +#               /pub/10.10.220.23/software" diff --git a/puppet/modules/git/files/init.d/CentOS/git-daemon b/puppet/modules/git/files/init.d/CentOS/git-daemon new file mode 100644 index 00000000..aed20756 --- /dev/null +++ b/puppet/modules/git/files/init.d/CentOS/git-daemon @@ -0,0 +1,75 @@ +#!/bin/bash +# puppet        Init script for running the git-daemon +# +# Author:       Marcel Haerry <mh+rpms(at)immerda.ch> +# +# chkconfig: - 98 02 +# +# description: Enables the git-daemon to serve various directories. By default it serves /srv/git +# processname: git-daemon +# config: /etc/sysconfig/git-daemon + +PATH=/usr/bin:/sbin:/bin:/usr/sbin +export PATH + +[ -f /etc/sysconfig/git-daemon ] && . /etc/sysconfig/git-daemon +lockfile=${LOCKFILE-/var/lock/subsys/git-daemon} +gitdir=${GITDIR-/srv/git} +gitvhost=${GITVHOST-no} +user=${GITUSER-nobody} +options=${OPTIONS-"--reuseaddr --verbose --detach"} +gitdaemon=${GITDAEMON-/usr/bin/git-daemon} +RETVAL=0 + +gitoptions="--user=${user} ${options}" +if [ $gitvhost = yes ]; then +	gitoptions="${gitoptions} --interpolated-path=${gitdir}/%H/%D" +else +	gitoptions="${gitoptions} --base-path=${gitdir}" +fi + +# Source function library. +. /etc/rc.d/init.d/functions + +start() { +    echo -n $"Starting git-daemon: " +    daemon $gitdaemon $gitoptions +    RETVAL=$? +    echo +    [ $RETVAL = 0 ] && touch ${lockfile} +    return $RETVAL +} + +stop() { +    echo -n $"Stopping git-daemon: " +    killproc $gitdaemon +    RETVAL=$? +    echo +    [ $RETVAL = 0 ] && rm -f ${lockfile} +} + +restart() { +    stop +    start +} + +case "$1" in +  start) +    start +    ;; +  stop)  +    stop +    ;; +  restart) +    restart +    ;; +  status) +    status $gitdaemon +    RETVAL=$? +    ;; +  *) +    echo $"Usage: $0 {start|stop|status|restart}" +    exit 1 +esac + +exit $RETVAL diff --git a/puppet/modules/git/files/init.d/Debian/git-daemon b/puppet/modules/git/files/init.d/Debian/git-daemon new file mode 100644 index 00000000..ab57c4a1 --- /dev/null +++ b/puppet/modules/git/files/init.d/Debian/git-daemon @@ -0,0 +1,151 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides:          git-daemon +# Required-Start:    $network $remote_fs $syslog +# Required-Stop:     $network $remote_fs $syslog +# Default-Start:     2 3 4 5 +# Default-Stop:      0 1 6 +# Short-Description: git-daemon service +# Description:       git-daemon makes git repositories available via the git +#                    protocol. +### END INIT INFO + +# Author: Antonio Ospite <ospite@studenti.unina.it> +# +# Please remove the "Author" lines above and replace them +# with your own name if you copy and modify this script. + +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/lib/git-core +DESC="git-daemon service" +NAME=git-daemon +DAEMON=/usr/lib/git-core/$NAME +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Fallback options values, we use these when +# the /etc/default/git-daemon file does not exist +RUN=no +USER=git +GROUP=git +REPOSITORIES="/srv/git/" + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# If ADVANCED_OPTS is empty, use a default setting +if [ "x$ADVANCED_OPTS" == "x" ]; +then +  ADVANCED_OPTS="--base-path=$REPOSITORIES $REPOSITORIES" +fi + +DAEMON_ARGS="--syslog --reuseaddr \ +             --user=$USER --group=$GROUP \ +             $ADVANCED_OPTS" + + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ +	# Return +	#   0 if daemon has been started +	#   1 if daemon was already running +	#   2 if daemon could not be started +	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ +		|| return 1 +	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --background --make-pidfile -- \ +		$DAEMON_ARGS \ +		|| return 2 + +  return 0 +} + +# +# Function that stops the daemon/service +# +do_stop() +{ +	# Return +	#   0 if daemon has been stopped +	#   1 if daemon was already stopped +	#   2 if daemon could not be stopped +	#   other if a failure occurred +	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME +	RETVAL="$?" +	[ "$RETVAL" = 2 ] && return 2 +	# Wait for children to finish too if this is a daemon that forks +	# and if the daemon is only ever run from this initscript. +	# If the above conditions are not satisfied then add some other code +	# that waits for the process to drop all resources that could be +	# needed by services started subsequently.  A last resort is to +	# sleep for some time. +	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON +	[ "$?" = 2 ] && return 2 +	# Many daemons don't delete their pidfiles when they exit. +	rm -f $PIDFILE +	return "$RETVAL" +} + +case "$1" in +  start) +	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" +	do_start +	case "$?" in +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; +	esac +	;; +  stop) +	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" +	do_stop +	case "$?" in +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; +	esac +	;; +  status) +       status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? +       ;; +  restart|force-reload) +	# +	# If the "reload" option is implemented then remove the +	# 'force-reload' alias +	# +	log_daemon_msg "Restarting $DESC" "$NAME" +	do_stop +	case "$?" in +	  0|1) +		do_start +		case "$?" in +			0) log_end_msg 0 ;; +			1) log_end_msg 1 ;; # Old process is still running +			*) log_end_msg 1 ;; # Failed to start +		esac +		;; +	  *) +	  	# Failed to stop +		log_end_msg 1 +		;; +	esac +	;; +  *) +	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 +	exit 3 +	;; +esac + +: diff --git a/puppet/modules/git/files/web/gitweb.conf b/puppet/modules/git/files/web/gitweb.conf new file mode 100644 index 00000000..88226aaa --- /dev/null +++ b/puppet/modules/git/files/web/gitweb.conf @@ -0,0 +1,53 @@ +# The gitweb config file is a fragment of perl code. You can set variables +# using "our $variable = value"; text from "#" character until the end of a +# line is ignored. See perlsyn(1) man page for details. +# +# See /usr/share/doc/gitweb-*/README and /usr/share/doc/gitweb-*/INSTALL for +# more details and available configuration variables. + +# Set the path to git projects.  This is an absolute filesystem path which will +# be prepended to the project path. +#our $projectroot = "/var/lib/git"; + +# Set the list of git base URLs used for URL to where fetch project from, i.e. +# the full URL is "$git_base_url/$project". By default this is empty +#our @git_base_url_list = qw(git://git.example.com +#                            ssh://git.example.com/var/lib/git); + +# Enable the 'blame' blob view, showing the last commit that modified +# each line in the file. This can be very CPU-intensive. Disabled by default +#$feature{'blame'}{'default'} = [1]; +# +# Allow projects to override the default setting via git config file. +# Example: gitweb.blame = 0|1; +#$feature{'blame'}{'override'} = 1; + +# Disable the 'snapshot' link, providing a compressed archive of any tree. This +# can potentially generate high traffic if you have large project. Enabled for +# .tar.gz snapshots by default. +# +# Value is a list of formats defined in %known_snapshot_formats that you wish +# to offer. +#$feature{'snapshot'}{'default'} = []; +# +# Allow projects to override the default setting via git config file. +# Example: gitweb.snapshot = tbz2,zip; (use "none" to disable) +#$feature{'snapshot'}{'override'} = 1; + +# Disable grep search, which will list the files in currently selected tree +# containing the given string. This can be potentially CPU-intensive, of +# course. Enabled by default. +#$feature{'grep'}{'default'} = [0]; +# +# Allow projects to override the default setting via git config file. +# Example: gitweb.grep = 0|1; +#$feature{'grep'}{'override'} = 1; + +# Disable the pickaxe search, which will list the commits that modified a given +# string in a file. This can be practical and quite faster alternative to +# 'blame', but still potentially CPU-intensive. Enabled by default. +#$feature{'pickaxe'}{'default'} = [0]; +# +# Allow projects to override the default setting via git config file. +# Example: gitweb.pickaxe = 0|1; +#$feature{'pickaxe'}{'override'} = 1; diff --git a/puppet/modules/git/files/xinetd.d/git b/puppet/modules/git/files/xinetd.d/git new file mode 100644 index 00000000..64c53e8b --- /dev/null +++ b/puppet/modules/git/files/xinetd.d/git @@ -0,0 +1,16 @@ +# default: off +# description: The git dæmon allows git repositories to be exported using +#	the git:// protocol. + +service git +{ +        disable		= no +        socket_type     = stream +        wait            = no +        user            = nobody +        server          = /usr/bin/git-daemon +        server_args     = --base-path=/srv/git --export-all --user-path=public_git --syslog --inetd --verbose +        log_on_failure  += USERID +# xinetd doesn't do this by default. bug #195265 +        flags		= IPv6 +} diff --git a/puppet/modules/git/files/xinetd.d/git.disabled b/puppet/modules/git/files/xinetd.d/git.disabled new file mode 100644 index 00000000..dcfae918 --- /dev/null +++ b/puppet/modules/git/files/xinetd.d/git.disabled @@ -0,0 +1,16 @@ +# default: off +# description: The git dæmon allows git repositories to be exported using +#	the git:// protocol. + +service git +{ +        disable		= yes +        socket_type     = stream +        wait            = no +        user            = nobody +        server          = /usr/bin/git-daemon +        server_args     = --base-path=/srv/git --export-all --user-path=public_git --syslog --inetd --verbose +        log_on_failure  += USERID +# xinetd doesn't do this by default. bug #195265 +        flags		= IPv6 +} diff --git a/puppet/modules/git/files/xinetd.d/git.vhosts b/puppet/modules/git/files/xinetd.d/git.vhosts new file mode 100644 index 00000000..98938206 --- /dev/null +++ b/puppet/modules/git/files/xinetd.d/git.vhosts @@ -0,0 +1,16 @@ +# default: off +# description: The git dæmon allows git repositories to be exported using +#	the git:// protocol. + +service git +{ +        disable		= no +        socket_type     = stream +        wait            = no +        user            = nobody +        server          = /usr/bin/git-daemon +        server_args     = --interpolated-path=/srv/git/%H/%D --syslog --inetd --verbose +        log_on_failure  += USERID +# xinetd doesn't do this by default. bug #195265 +        flags		= IPv6 +} diff --git a/puppet/modules/git/manifests/base.pp b/puppet/modules/git/manifests/base.pp new file mode 100644 index 00000000..e6188390 --- /dev/null +++ b/puppet/modules/git/manifests/base.pp @@ -0,0 +1,7 @@ +class git::base { + +  package { 'git': +    ensure => present, +    alias => 'git', +  } +} diff --git a/puppet/modules/git/manifests/centos.pp b/puppet/modules/git/manifests/centos.pp new file mode 100644 index 00000000..96344756 --- /dev/null +++ b/puppet/modules/git/manifests/centos.pp @@ -0,0 +1,2 @@ +class git::centos inherits git::base { +} diff --git a/puppet/modules/git/manifests/changes.pp b/puppet/modules/git/manifests/changes.pp new file mode 100644 index 00000000..71112051 --- /dev/null +++ b/puppet/modules/git/manifests/changes.pp @@ -0,0 +1,33 @@ +# Usage +# git::changes { name: +#   cwd    =>  "/path/to/git/" +#   user   =>  "me", +#   ensure =>  {*assume-unchanged*, tracked} +# } +# + +define git::changes ( $cwd, $user, $ensure='assume-unchanged' ) { + +  case $ensure { +    default: { err ( "unknown ensure value '${ensure}'" ) } + +    assume-unchanged: { +      exec { "assume-unchanged ${name}": +        command => "/usr/bin/git update-index --assume-unchanged ${name}", +        cwd     => $cwd, +        user    => $user, +        unless  => "/usr/bin/git ls-files -v | grep '^[ch] ${name}'", +      } +    } + +    tracked: { +      exec { "track changes ${name}": +        command => "/usr/bin/git update-index --no-assume-unchanged ${name}", +        cwd     => $cwd, +        user    => $user, +        onlyif  => "/usr/bin/git ls-files -v | grep '^[ch] ${name}'", +      } +    } +  } +} + diff --git a/puppet/modules/git/manifests/clone.pp b/puppet/modules/git/manifests/clone.pp new file mode 100644 index 00000000..29f0b2b3 --- /dev/null +++ b/puppet/modules/git/manifests/clone.pp @@ -0,0 +1,60 @@ +# submodules: Whether we should initialize and update +#             submodules as well +#             Default: false +# clone_before: before which resources a cloning should +#               happen. This is releveant in combination +#               with submodules as the exec of submodules +#               requires the `cwd` and you might get a +#               dependency cycle if you manage $projectroot +#               somewhere else. +define git::clone( +  $ensure = present, +  $git_repo, +  $projectroot, +  $submodules = false, +  $clone_before = 'absent', +  $cloneddir_user='root', +  $cloneddir_group='0', +  $cloneddir_restrict_mode=true +){ +  case $ensure { +    absent: { +      exec{"rm -rf $projectroot": +        onlyif => "test -d  $projectroot", +      } +    } +    default: { +      require ::git +      exec {"git-clone_${name}": +        command => "git clone --no-hardlinks ${git_repo} ${projectroot}", +        creates => "${projectroot}/.git", +        user => root, +        notify => Exec["git-clone-chown_${name}"], +      } +      if $clone_before != 'absent' { +        Exec["git-clone_${name}"]{ +          before => $clone_before, +        } +      } +      if $submodules { +        exec{"git-submodules_${name}": +          command => "git submodule init && git submodule update", +          cwd => $projectroot, +          refreshonly => true, +          subscribe => Exec["git-clone_${name}"], +        } +      } +      exec {"git-clone-chown_${name}": +        command => "chown -R ${cloneddir_user}:${cloneddir_group} ${projectroot};chmod -R og-rwx ${projectroot}/.git", +        refreshonly => true +      } +      if $cloneddir_restrict_mode { +        exec {"git-clone-chmod_${name}": +          command => "chmod -R o-rwx ${projectroot}", +          refreshonly => true, +          subscribe => Exec["git-clone_${name}"], +        } +      } +    } +  } +} diff --git a/puppet/modules/git/manifests/daemon.pp b/puppet/modules/git/manifests/daemon.pp new file mode 100644 index 00000000..1e85ff84 --- /dev/null +++ b/puppet/modules/git/manifests/daemon.pp @@ -0,0 +1,17 @@ +class git::daemon { + +  include git + +  case $operatingsystem { +    centos: { include git::daemon::centos } +    debian: { include git::daemon::base } +  } + +  if $use_shorewall { +    include shorewall::rules::gitdaemon +  } + +  if $use_nagios { +    nagios::service { "git-daemon": check_command => "check_git!${fqdn}"; } +  } +} diff --git a/puppet/modules/git/manifests/daemon/base.pp b/puppet/modules/git/manifests/daemon/base.pp new file mode 100644 index 00000000..6a03d4fd --- /dev/null +++ b/puppet/modules/git/manifests/daemon/base.pp @@ -0,0 +1,31 @@ +class git::daemon::base inherits git::base { + +  file { 'git-daemon_initscript': +    source => [ "puppet://$server/modules/site_git/init.d/${fqdn}/git-daemon", +                "puppet://$server/modules/site_git/init.d/${operatingsystem}/git-daemon", +                "puppet://$server/modules/site_git/init.d/git-daemon", +                "puppet://$server/modules/git/init.d/${operatingsystem}/git-daemon", +                "puppet://$server/modules/git/init.d/git-daemon" ], +    require => Package['git'], +    path => "/etc/init.d/git-daemon", +    owner => root, group => 0, mode => 0755; +  } +   +  file { 'git-daemon_config': +    source => [ "puppet://$server/modules/site_git/config/${fqdn}/git-daemon", +                "puppet://$server/modules/site_git/config/${operatingsystem}/git-daemon", +                "puppet://$server/modules/site_git/config/git-daemon", +                "puppet://$server/modules/git/config/${operatingsystem}/git-daemon", +                "puppet://$server/modules/git/config/git-daemon" ], +    require => Package['git'], +    path => "/etc/default/git-daemon", +    owner => root, group => 0, mode => 0644; +  } +   +  service { 'git-daemon': +    ensure => running, +    enable => true, +    hasstatus => true, +    require => [ File['git-daemon_initscript'], File['git-daemon_config'] ], +  } +} diff --git a/puppet/modules/git/manifests/daemon/centos.pp b/puppet/modules/git/manifests/daemon/centos.pp new file mode 100644 index 00000000..e276259d --- /dev/null +++ b/puppet/modules/git/manifests/daemon/centos.pp @@ -0,0 +1,19 @@ +class git::daemon::centos inherits git::daemon::base { + +  package { 'git-daemon': +    ensure => installed, +    require => Package['git'], +    alias => 'git-daemon', +  } +   +  File['git-daemon_initscript'] { +    path => '/etc/init.d/git-daemon', +    require +> Package['git-daemon'], +  } + +  File['git-daemon_config'] { +    path => '/etc/init.d/git-daemon', +    require +> Package['git-daemon'], +  } + +} diff --git a/puppet/modules/git/manifests/daemon/disable.pp b/puppet/modules/git/manifests/daemon/disable.pp new file mode 100644 index 00000000..c044e962 --- /dev/null +++ b/puppet/modules/git/manifests/daemon/disable.pp @@ -0,0 +1,33 @@ +class git::daemon::disable inherits git::daemon::base { + +  if defined(Package['git-daemon']) { +    Package['git-daemon'] { +      ensure => absent, +    } +  } + +  File['git-daemon_initscript'] {  +    ensure => absent, +  } +   +  File['git-daemon_config'] { +    ensure => absent, +  } +   +  Service['git-daemon'] { +    ensure => stopped, +    enable => false, +    require => undef, +    before => File['git-daemon_initscript'], +  } + +  if $use_shorewall { +    include shorewall::rules::gitdaemon::absent +  } + +  if $use_nagios { +    nagios::service { "git-daemon": check_command => "check_git!${fqdn}", ensure => absent; } +  } +} + + diff --git a/puppet/modules/git/manifests/daemon/vhosts.pp b/puppet/modules/git/manifests/daemon/vhosts.pp new file mode 100644 index 00000000..9591330f --- /dev/null +++ b/puppet/modules/git/manifests/daemon/vhosts.pp @@ -0,0 +1,10 @@ +class git::daemon::vhosts inherits git::daemon { + +  File['git-daemon_config']{ +    source => [ "puppet://$server/modules/site_git/config/${fqdn}/git-daemon.vhosts", +                "puppet://$server/modules/site_git/config/${operatingsystem}/git-daemon.vhosts", +                "puppet://$server/modules/site_git/config/git-daemon.vhosts", +                "puppet://$server/modules/git/config/${operatingsystem}/git-daemon.vhosts", +                "puppet://$server/modules/git/config/git-daemon.vhosts" ], +  } +} diff --git a/puppet/modules/git/manifests/debian.pp b/puppet/modules/git/manifests/debian.pp new file mode 100644 index 00000000..2e63d692 --- /dev/null +++ b/puppet/modules/git/manifests/debian.pp @@ -0,0 +1,6 @@ +class git::debian inherits git::base { + +  Package['git'] { +    name => 'git-core', +  } +} diff --git a/puppet/modules/git/manifests/init.pp b/puppet/modules/git/manifests/init.pp new file mode 100644 index 00000000..4693af75 --- /dev/null +++ b/puppet/modules/git/manifests/init.pp @@ -0,0 +1,25 @@ +# +# git module +# +# Copyright 2008, Puzzle ITC +# Marcel Härry haerry+puppet(at)puzzle.ch +# Simon Josi josi+puppet(at)puzzle.ch +# +# This program is free software; you can redistribute  +# it and/or modify it under the terms of the GNU  +# General Public License version 3 as published by  +# the Free Software Foundation. +# + +class git { + +  case $operatingsystem { +    debian: { include git::debian } +    centos: { include git::centos } +  } + +  if $use_shorewall { +    include shorewall::rules::out::git +  } + +} diff --git a/puppet/modules/git/manifests/svn.pp b/puppet/modules/git/manifests/svn.pp new file mode 100644 index 00000000..ea934749 --- /dev/null +++ b/puppet/modules/git/manifests/svn.pp @@ -0,0 +1,10 @@ +# manifests/svn.pp + +class git::svn { +  include ::git +  include subversion + +  package { 'git-svn': +    require => [ Package['git'], Package['subversion'] ], +  } +} diff --git a/puppet/modules/git/manifests/web.pp b/puppet/modules/git/manifests/web.pp new file mode 100644 index 00000000..3cf5139e --- /dev/null +++ b/puppet/modules/git/manifests/web.pp @@ -0,0 +1,20 @@ +class git::web { +  include git + +  package { 'gitweb': +    ensure => present, +    require => Package['git'], +  } + +  file { '/etc/gitweb.d': +    ensure => directory, +    owner => root, group => 0, mode => 0755; +  } +  file { '/etc/gitweb.conf': +    source => [ "puppet:///modules/site_git/web/${fqdn}/gitweb.conf", +                "puppet:///modules/site_git/web/gitweb.conf", +                "puppet:///modules/git/web/gitweb.conf" ], +    require => Package['gitweb'], +    owner => root, group => 0, mode => 0644; +  } +} diff --git a/puppet/modules/git/manifests/web/absent.pp b/puppet/modules/git/manifests/web/absent.pp new file mode 100644 index 00000000..4d0dba33 --- /dev/null +++ b/puppet/modules/git/manifests/web/absent.pp @@ -0,0 +1,17 @@ +class git::web::absent { + +  package { 'gitweb': +    ensure => absent, +  }  + +  file { '/etc/gitweb.d': +    ensure => absent, +    purge => true, +    force => true, +    recurse => true, +  }  +  file { '/etc/gitweb.conf': +    ensure => absent, +  }  +} + diff --git a/puppet/modules/git/manifests/web/lighttpd.pp b/puppet/modules/git/manifests/web/lighttpd.pp new file mode 100644 index 00000000..980e23c0 --- /dev/null +++ b/puppet/modules/git/manifests/web/lighttpd.pp @@ -0,0 +1,7 @@ +class git::web::lighttpd { +  include ::lighttpd  + +  lighttpd::config::file{'lighttpd-gitweb': +    content => 'global { server.modules += ("mod_rewrite", "mod_redirect", "mod_alias", "mod_setenv", "mod_cgi" ) }', +  } +} diff --git a/puppet/modules/git/manifests/web/repo.pp b/puppet/modules/git/manifests/web/repo.pp new file mode 100644 index 00000000..da6f74f0 --- /dev/null +++ b/puppet/modules/git/manifests/web/repo.pp @@ -0,0 +1,56 @@ +# domain: the domain under which this repo will be avaiable +# projectroot: where the git repos are listened +# projects_list: which repos to export +# +# logmode: +#   - default: Do normal logging including ips +#   - anonym: Don't log ips +define git::web::repo( +  $ensure = 'present', +  $projectroot = 'absent', +  $projects_list = 'absent', +  $logmode = 'default', +  $sitename = 'absent' +){ +  if ($ensure == 'present') and (($projects_list == 'absent') or ($projectroot == 'absent')){ +    fail("You have to pass \$project_list and \$projectroot for ${name} if it should be present!") +  } +  if $ensure == 'present' { include git::web } +  $gitweb_url = $name +  case $gitweb_sitename { +    'absent': { $gitweb_sitename = "${name} git repository" } +    default: { $gitweb_sitename = $sitename } +  } +  $gitweb_config = "/etc/gitweb.d/${name}.conf" +  file{"${gitweb_config}": } +  if $ensure == 'present' { +    File["${gitweb_config}"]{ +      content => template("git/web/config") +    } +  } else { +    File["${gitweb_config}"]{ +      ensure => absent, +    } +  } +  case $gitweb_webserver { +    'lighttpd': { +      git::web::repo::lighttpd{$name: +        ensure => $ensure, +        logmode => $logmode, +        gitweb_url => $gitweb_url, +        gitweb_config => $gitweb_config, +      } +    } +    'apache': { +      apache::vhost::gitweb{$gitweb_url: +        logmode => $logmode, +        ensure => $ensure, +      } +    } +    default: { +      if ($ensure == 'present') { +        fail("no supported \$gitweb_webserver defined on ${fqdn}, so can't do git::web::repo: ${name}") +      } +    } +  } +} diff --git a/puppet/modules/git/manifests/web/repo/lighttpd.pp b/puppet/modules/git/manifests/web/repo/lighttpd.pp new file mode 100644 index 00000000..11cee4ce --- /dev/null +++ b/puppet/modules/git/manifests/web/repo/lighttpd.pp @@ -0,0 +1,16 @@ +# logmode: +#   - default: Do normal logging including ips +#   - anonym: Don't log ips +define git::web::repo::lighttpd( +  $ensure = 'present', +  $gitweb_url, +  $logmode = 'default', +  $gitweb_config +){ +  if $ensure == 'present' { include git::web::lighttpd } + +  lighttpd::vhost::file{$name: +     ensure => $ensure, +     content => template('git/web/lighttpd'); +  } +} diff --git a/puppet/modules/git/templates/web/config b/puppet/modules/git/templates/web/config new file mode 100644 index 00000000..5286f6a6 --- /dev/null +++ b/puppet/modules/git/templates/web/config @@ -0,0 +1,31 @@ +# Include the global configuration, if found. +do "/etc/gitweb.conf" if -e "/etc/gitweb.conf"; + +# Point to projects.list file generated by gitosis. +# Here gitosis manages the user "git", who has a +# home directory of /srv/example.com/git +$projects_list = "<%= projects_list %>"; + +# Where the actual repositories are located. +$projectroot = "<%= projectroot %>"; + +# By default, gitweb will happily let people browse any repository +# they guess the name of. This may or may not be what you wanted.  I +# choose to allow gitweb to show only repositories that git-daemon +# is already sharing anonymously. +$export_ok = "git-daemon-export-ok"; + +# Alternatively, you could set these, to allow exactly the things in +# projects.list, which in this case is the repos with gitweb=yes +# in gitosis.conf. This means you don't need daemon=yes, but you +# can't have repositories hidden but browsable if you know the name. +# And note gitweb already allows downloading the full repository, +# so you might as well serve git-daemon too. +# $export_ok = ""; +# $strict_export = "true"; + +# A list of base urls where all the repositories can be cloned from. +# Easier than having per-repository cloneurl files. +@git_base_url_list = ('git://<%= gitweb_url %>'); + +$GITWEB_SITENAME = "<%= gitweb_sitename %>" diff --git a/puppet/modules/git/templates/web/lighttpd b/puppet/modules/git/templates/web/lighttpd new file mode 100644 index 00000000..cf244691 --- /dev/null +++ b/puppet/modules/git/templates/web/lighttpd @@ -0,0 +1,21 @@ +$HTTP["host"] == "<%= gitweb_url %>" { +    url.redirect += ( +      "^$" => "/", +    ) + +    <%- if logmode.to_s == 'anonym' -%> +    accesslog.format = "127.0.0.1 %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" +    <%- end -%> + +    alias.url += ( +      "/static/gitweb.css" => "/var/www/git/static/gitweb.css", +      "/static/git-logo.png" => "/var/www/git/static/git-logo.png", +      "/static/git-favicon.png" => "/var/www/git/static/git-favicon.png", +      "/" => "/var/www/git/gitweb.cgi", +    ) + +    setenv.add-environment = ( +      "GITWEB_CONFIG" => "<%= gitweb_config %>" +    ) +    cgi.assign = ( ".cgi" => "" ) +} diff --git a/puppet/modules/haveged/manifests/init.pp b/puppet/modules/haveged/manifests/init.pp new file mode 100644 index 00000000..8f901937 --- /dev/null +++ b/puppet/modules/haveged/manifests/init.pp @@ -0,0 +1,16 @@ +class haveged { + +  package { 'haveged': +    ensure => present, +  } + +  service { 'haveged': +    ensure     => running, +    hasrestart => true, +    hasstatus  => true, +    enable     => true, +    require    => Package['haveged']; +  } + +  include site_check_mk::agent::haveged +} diff --git a/puppet/modules/journald/manifests/init.pp b/puppet/modules/journald/manifests/init.pp new file mode 100644 index 00000000..879baba4 --- /dev/null +++ b/puppet/modules/journald/manifests/init.pp @@ -0,0 +1,7 @@ +class journald { + +    service { 'systemd-journald': +      ensure => running, +      enable => true, +    } +} diff --git a/puppet/modules/leap/manifests/cli/install.pp b/puppet/modules/leap/manifests/cli/install.pp new file mode 100644 index 00000000..25e87033 --- /dev/null +++ b/puppet/modules/leap/manifests/cli/install.pp @@ -0,0 +1,46 @@ +# installs leap_cli on node +class leap::cli::install ( $source = false ) { +  if $source { +    # needed for building leap_cli from source +    include ::git +    include ::rubygems + +    class { '::ruby': +      install_dev => true +    } + +    class { 'bundler::install': install_method => 'package' } + +    Class[Ruby] -> +      Class[rubygems] -> +      Class[bundler::install] + + +    vcsrepo { '/srv/leap/cli': +      ensure   => present, +      force    => true, +      revision => 'develop', +      provider => 'git', +      source   => 'https://leap.se/git/leap_cli.git', +      owner    => 'root', +      group    => 'root', +      notify   => Exec['install_leap_cli'], +      require  => Package['git'] +    } + +    exec { 'install_leap_cli': +      command     => '/usr/bin/rake build && /usr/bin/rake install', +      cwd         => '/srv/leap/cli', +      user        => 'root', +      environment => 'USER=root', +      refreshonly => true, +      require     => [ Class[bundler::install] ] +    } +  } +  else { +    package { 'leap_cli': +      ensure   => installed, +      provider => gem +    } +  } +} diff --git a/puppet/modules/leap/manifests/init.pp b/puppet/modules/leap/manifests/init.pp new file mode 100644 index 00000000..bbae3781 --- /dev/null +++ b/puppet/modules/leap/manifests/init.pp @@ -0,0 +1,3 @@ +class leap { + +}
\ No newline at end of file diff --git a/puppet/modules/leap/manifests/logfile.pp b/puppet/modules/leap/manifests/logfile.pp new file mode 100644 index 00000000..adb3ca8a --- /dev/null +++ b/puppet/modules/leap/manifests/logfile.pp @@ -0,0 +1,34 @@ +# +# make syslog log to a particular file for a particular process. +# +# arguments: +# +#   * name: what config files are named as (eg.  /etc/rsyslog.d/50-$name.conf) +#   * log: the full path of the log file (defaults to /var/log/leap/$name.log +#   * process: the syslog tag to filter on (defaults to name) +# +define leap::logfile($process = $name, $log = undef) { +  if $log { +    $logfile = $log +  } else { +    $logfile = "/var/log/leap/${name}.log" +  } + +  rsyslog::snippet { "50-${name}": +    content => template('leap/rsyslog.erb') +  } + +  augeas { +    "logrotate_${name}": +      context => "/files/etc/logrotate.d/${name}/rule", +      changes => [ +        "set file ${logfile}", +        'set rotate 5', +        'set schedule daily', +        'set compress compress', +        'set missingok missingok', +        'set ifempty notifempty', +        'set copytruncate copytruncate' +      ] +  } +} diff --git a/puppet/modules/leap/templates/rsyslog.erb b/puppet/modules/leap/templates/rsyslog.erb new file mode 100644 index 00000000..7bb5316f --- /dev/null +++ b/puppet/modules/leap/templates/rsyslog.erb @@ -0,0 +1,5 @@ +if $programname startswith '<%= @process %>' then { +  action(type="omfile" file="<%= @logfile %>" template="RSYSLOG_TraditionalFileFormat") +  stop +} + diff --git a/puppet/modules/leap_mx/manifests/init.pp b/puppet/modules/leap_mx/manifests/init.pp new file mode 100644 index 00000000..d758e3ab --- /dev/null +++ b/puppet/modules/leap_mx/manifests/init.pp @@ -0,0 +1,119 @@ +# deploy leap mx service +class leap_mx { + +  $leap_mx          = hiera('couchdb_leap_mx_user') +  $couchdb_user     = $leap_mx['username'] +  $couchdb_password = $leap_mx['password'] + +  $couchdb_host     = 'localhost' +  $couchdb_port     = '4096' + +  $sources          = hiera('sources') + +  include soledad::common + +  # +  # USER AND GROUP +  # +  # Make the user for leap-mx. This user is where all legitimate, non-system +  # mail is delivered so leap-mx can process it. Previously, we let the system +  # pick a uid/gid, but we need to know what they are set to in order to set the +  # virtual_uid_maps and virtual_gid_maps. Its a bit overkill write a fact just +  # for this, so instead we pick arbitrary numbers that seem unlikely to be used +  # and then use them in the postfix configuration + +  group { 'leap-mx': +    ensure    => present, +    gid       => 42424, +    allowdupe => false; +  } + +  user { 'leap-mx': +    ensure     => present, +    comment    => 'Leap Mail', +    allowdupe  => false, +    uid        => 42424, +    gid        => 'leap-mx', +    home       => '/var/mail/leap-mx', +    shell      => '/bin/false', +    managehome => true, +    require    => Group['leap-mx']; +  } + +  file { +    '/var/mail/leap-mx': +      ensure  => directory, +      owner   => 'leap-mx', +      group   => 'leap-mx', +      mode    => '0755', +      require => User['leap-mx']; + +    '/var/mail/leap-mx/Maildir': +      ensure => directory, +      owner  => 'leap-mx', +      group  => 'leap-mx', +      mode   => '0700'; + +    '/var/mail/leap-mx/Maildir/new': +      ensure => directory, +      owner  => 'leap-mx', +      group  => 'leap-mx', +      mode   => '0700'; + +    '/var/mail/leap-mx/Maildir/cur': +      ensure => directory, +      owner  => 'leap-mx', +      group  => 'leap-mx', +      mode   => '0700'; + +    '/var/mail/leap-mx/Maildir/tmp': +      ensure => directory, +      owner  => 'leap-mx', +      group  => 'leap-mx', +      mode   => '0700'; +  } + +  # +  # LEAP-MX CONFIG +  # + +  file { '/etc/leap/mx.conf': +    content => template('leap_mx/mx.conf.erb'), +    owner   => 'leap-mx', +    group   => 'leap-mx', +    mode    => '0600', +    notify  => Service['leap-mx']; +  } + +  leap::logfile { 'leap-mx': +    log     => '/var/log/leap/mx.log', +    process => 'leap-mx' +  } + +  # +  # LEAP-MX CODE AND DEPENDENCIES +  # + +  package { +    $sources['leap-mx']['package']: +      ensure  => $sources['leap-mx']['revision'], +      require => [ +        Class['site_apt::leap_repo'], +        User['leap-mx'] ]; + +    'leap-keymanager': +      ensure => latest; +  } + +  # +  # LEAP-MX DAEMON +  # + +  service { 'leap-mx': +    ensure     => running, +    enable     => true, +    hasstatus  => true, +    hasrestart => true, +    require    => [ Package['leap-mx'] ]; +  } +} diff --git a/puppet/modules/leap_mx/templates/mx.conf.erb b/puppet/modules/leap_mx/templates/mx.conf.erb new file mode 100644 index 00000000..b54b3a86 --- /dev/null +++ b/puppet/modules/leap_mx/templates/mx.conf.erb @@ -0,0 +1,18 @@ +[mail1] +path=/var/mail/leap-mx/Maildir +recursive=True + +[couchdb] +user=<%= @couchdb_user %> +password=<%= @couchdb_password %> +server=<%= @couchdb_host %> +port=<%= @couchdb_port %> + +[alias map] +port=4242 + +[check recipient] +port=2244 + +[fingerprint map] +port=2424 diff --git a/puppet/modules/lsb/manifests/base.pp b/puppet/modules/lsb/manifests/base.pp new file mode 100644 index 00000000..9dc8d5a4 --- /dev/null +++ b/puppet/modules/lsb/manifests/base.pp @@ -0,0 +1,3 @@ +class lsb::base { +  package{'lsb': ensure => present } +} diff --git a/puppet/modules/lsb/manifests/centos.pp b/puppet/modules/lsb/manifests/centos.pp new file mode 100644 index 00000000..b7006187 --- /dev/null +++ b/puppet/modules/lsb/manifests/centos.pp @@ -0,0 +1,5 @@ +class lsb::centos inherits lsb::base { +  Package['lsb']{ +    name => 'redhat-lsb', +  } +} diff --git a/puppet/modules/lsb/manifests/debian.pp b/puppet/modules/lsb/manifests/debian.pp new file mode 100644 index 00000000..c32070f3 --- /dev/null +++ b/puppet/modules/lsb/manifests/debian.pp @@ -0,0 +1,6 @@ +class lsb::debian inherits lsb::base { +  Package['lsb']{ +    name => 'lsb-release', +    require => undef, +  } +} diff --git a/puppet/modules/lsb/manifests/init.pp b/puppet/modules/lsb/manifests/init.pp new file mode 100644 index 00000000..85b34e1f --- /dev/null +++ b/puppet/modules/lsb/manifests/init.pp @@ -0,0 +1,6 @@ +class lsb { +  case $::operatingsystem { +    debian,ubuntu: { include lsb::debian } +    centos: { include lsb::centos } +  } +} diff --git a/puppet/modules/ntp/.fixtures.yml b/puppet/modules/ntp/.fixtures.yml new file mode 100644 index 00000000..a4b98014 --- /dev/null +++ b/puppet/modules/ntp/.fixtures.yml @@ -0,0 +1,5 @@ +fixtures: +  repositories: +    "stdlib": "git://github.com/puppetlabs/puppetlabs-stdlib.git" +  symlinks: +    "ntp": "#{source_dir}" diff --git a/puppet/modules/ntp/.gitignore b/puppet/modules/ntp/.gitignore new file mode 100644 index 00000000..49cf4650 --- /dev/null +++ b/puppet/modules/ntp/.gitignore @@ -0,0 +1,3 @@ +pkg/ +metadata.json +Gemfile.lock diff --git a/puppet/modules/ntp/.nodeset.yml b/puppet/modules/ntp/.nodeset.yml new file mode 100644 index 00000000..cbd0d57b --- /dev/null +++ b/puppet/modules/ntp/.nodeset.yml @@ -0,0 +1,35 @@ +--- +default_set: 'centos-64-x64' +sets: +  'centos-59-x64': +    nodes: +      "main.foo.vm": +        prefab: 'centos-59-x64' +  'centos-64-x64': +    nodes: +      "main.foo.vm": +        prefab: 'centos-64-x64' +  'fedora-18-x64': +    nodes: +      "main.foo.vm": +        prefab: 'fedora-18-x64' +  'debian-607-x64': +    nodes: +      "main.foo.vm": +        prefab: 'debian-607-x64' +  'debian-70rc1-x64': +    nodes: +      "main.foo.vm": +        prefab: 'debian-70rc1-x64' +  'ubuntu-server-10044-x64': +    nodes: +      "main.foo.vm": +        prefab: 'ubuntu-server-10044-x64' +  'ubuntu-server-12042-x64': +    nodes: +      "main.foo.vm": +        prefab: 'ubuntu-server-12042-x64' +  'sles-11sp1-x64': +    nodes: +      "main.foo.vm": +        prefab: 'sles-11sp1-x64' diff --git a/puppet/modules/ntp/.travis.yml b/puppet/modules/ntp/.travis.yml new file mode 100644 index 00000000..e9f0e84b --- /dev/null +++ b/puppet/modules/ntp/.travis.yml @@ -0,0 +1,40 @@ +--- +branches: +  only: +  - master +language: ruby +bundler_args: --without development +script: "bundle exec rake spec SPEC_OPTS='--format documentation'" +after_success: +  - git clone -q git://github.com/puppetlabs/ghpublisher.git .forge-releng +  - .forge-releng/publish +rvm: +- 1.8.7 +- 1.9.3 +- 2.0.0 +env: +  matrix: +    - PUPPET_GEM_VERSION="~> 2.7.0" +    - PUPPET_GEM_VERSION="~> 3.0.0" +    - PUPPET_GEM_VERSION="~> 3.1.0" +    - PUPPET_GEM_VERSION="~> 3.2.0" +  global: +    - PUBLISHER_LOGIN=puppetlabs +    - secure: |- +        ZiIkYd9+CdPzpwSjFPnVkCx1FIlipxpbdyD33q94h2Tj5zXjNb1GXizVy0NR +        kVxGhU5Ld8y9z8DTqKRgCI1Yymg3H//OU++PKLOQj/X5juWVR4URBNPeBOzu +        IJBDl1MADKA4i1+jAZPpz4mTvTtKS4pWKErgCSmhSfsY1hs7n6c= +matrix: +  exclude: +    - rvm: 1.9.3 +      env: PUPPET_GEM_VERSION="~> 2.7.0" +    - rvm: 2.0.0 +      env: PUPPET_GEM_VERSION="~> 2.7.0" +    - rvm: 2.0.0 +      env: PUPPET_GEM_VERSION="~> 3.0.0" +    - rvm: 2.0.0 +      env: PUPPET_GEM_VERSION="~> 3.1.0" +    - rvm: 1.8.7 +      env: PUPPET_GEM_VERSION="~> 3.2.0" +notifications: +  email: false diff --git a/puppet/modules/ntp/CHANGELOG b/puppet/modules/ntp/CHANGELOG new file mode 100644 index 00000000..8be6c4e0 --- /dev/null +++ b/puppet/modules/ntp/CHANGELOG @@ -0,0 +1,61 @@ +2013-07-31 - Version 2.0.0 + +Summary: + +The 2.0 release focuses on merging all the distro specific +templates into a single reusable template across all platforms. + +To aid in that goal we now allow you to change the driftfile, +ntp keys, and perferred_servers. + +Backwards-incompatible changes: + +As all the distro specific templates have been removed and a +unified one created you may be missing functionality you +previously relied on.  Please test carefully before rolling +out globally. + +Configuration directives that might possibly be affected: +- `filegen` +- `fudge` (for virtual machines) +- `keys` +- `logfile` +- `restrict` +- `restrictkey` +- `statistics` +- `trustedkey` + +Features: +- All templates merged into a single template. +- NTP Keys support added. +- Add preferred servers support. +- Parameters in `ntp` class: + - `driftfile`: path for the ntp driftfile. + - `keys_enable`: Enable NTP keys feature. + - `keys_file`: Path for the NTP keys file. + - `keys_trusted`: Which keys to trust. + - `keys_controlkey`: Which key to use for the control key. + - `keys_requestkey`: Which key to use for the request key. + - `preferred_servers`: Array of servers to prefer. + - `restrict`: Array of restriction options to apply. + +2013-07-15 - Version 1.0.1 +Bugfixes: +- Fix deprecated warning in `autoupdate` parameter. +- Correctly quote is_virtual fact. + +2013-07-08 - Version 1.0.0 +Features: +- Completely refactored to split across several classes. +- rspec-puppet tests rewritten to cover more options. +- rspec-system tests added. +- ArchLinux handled via osfamily instead of special casing. +- parameters in `ntp` class: + - `autoupdate`: deprecated in favor of directly setting package_ensure. + - `panic`: set to false if you wish to allow large clock skews.  + +2011-11-10 Dan Bode <dan@puppetlabs.com> - 0.0.4 +Add Amazon Linux as a supported platform +Add unit tests +2011-06-16 Jeff McCune <jeff@puppetlabs.com> - 0.0.3 +Initial release under puppetlabs diff --git a/puppet/modules/ntp/CONTRIBUTING.md b/puppet/modules/ntp/CONTRIBUTING.md new file mode 100644 index 00000000..a2b1d77b --- /dev/null +++ b/puppet/modules/ntp/CONTRIBUTING.md @@ -0,0 +1,9 @@ +Puppet Labs modules on the Puppet Forge are open projects, and community contributions +are essential for keeping them great. We can’t access the huge number of platforms and +myriad of hardware, software, and deployment configurations that Puppet is intended to serve. + +We want to keep it as easy as possible to contribute changes so that our modules work +in your environment. There are a few guidelines that we need contributors to follow so +that we can have a chance of keeping on top of things. + +You can read the complete module contribution guide [on the Puppet Labs wiki.](http://projects.puppetlabs.com/projects/module-site/wiki/Module_contributing) diff --git a/puppet/modules/ntp/Gemfile b/puppet/modules/ntp/Gemfile new file mode 100644 index 00000000..4e733308 --- /dev/null +++ b/puppet/modules/ntp/Gemfile @@ -0,0 +1,19 @@ +source 'https://rubygems.org' + +group :development, :test do +  gem 'rake',                    :require => false +  gem 'puppetlabs_spec_helper',  :require => false +  gem 'rspec-system-puppet',     :require => false +  gem 'puppet-lint',             :require => false +  gem 'serverspec',              :require => false +  gem 'rspec-system-serverspec', :require => false +  gem 'vagrant-wrapper',         :require => false +end + +if puppetversion = ENV['PUPPET_GEM_VERSION'] +  gem 'puppet', puppetversion, :require => false +else +  gem 'puppet', :require => false +end + +# vim:ft=ruby diff --git a/puppet/modules/ntp/LICENSE b/puppet/modules/ntp/LICENSE new file mode 100644 index 00000000..57bc88a1 --- /dev/null +++ b/puppet/modules/ntp/LICENSE @@ -0,0 +1,202 @@ +                                 Apache License +                           Version 2.0, January 2004 +                        http://www.apache.org/licenses/ + +   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +   1. Definitions. + +      "License" shall mean the terms and conditions for use, reproduction, +      and distribution as defined by Sections 1 through 9 of this document. + +      "Licensor" shall mean the copyright owner or entity authorized by +      the copyright owner that is granting the License. + +      "Legal Entity" shall mean the union of the acting entity and all +      other entities that control, are controlled by, or are under common +      control with that entity. For the purposes of this definition, +      "control" means (i) the power, direct or indirect, to cause the +      direction or management of such entity, whether by contract or +      otherwise, or (ii) ownership of fifty percent (50%) or more of the +      outstanding shares, or (iii) beneficial ownership of such entity. + +      "You" (or "Your") shall mean an individual or Legal Entity +      exercising permissions granted by this License. + +      "Source" form shall mean the preferred form for making modifications, +      including but not limited to software source code, documentation +      source, and configuration files. + +      "Object" form shall mean any form resulting from mechanical +      transformation or translation of a Source form, including but +      not limited to compiled object code, generated documentation, +      and conversions to other media types. + +      "Work" shall mean the work of authorship, whether in Source or +      Object form, made available under the License, as indicated by a +      copyright notice that is included in or attached to the work +      (an example is provided in the Appendix below). + +      "Derivative Works" shall mean any work, whether in Source or Object +      form, that is based on (or derived from) the Work and for which the +      editorial revisions, annotations, elaborations, or other modifications +      represent, as a whole, an original work of authorship. For the purposes +      of this License, Derivative Works shall not include works that remain +      separable from, or merely link (or bind by name) to the interfaces of, +      the Work and Derivative Works thereof. + +      "Contribution" shall mean any work of authorship, including +      the original version of the Work and any modifications or additions +      to that Work or Derivative Works thereof, that is intentionally +      submitted to Licensor for inclusion in the Work by the copyright owner +      or by an individual or Legal Entity authorized to submit on behalf of +      the copyright owner. For the purposes of this definition, "submitted" +      means any form of electronic, verbal, or written communication sent +      to the Licensor or its representatives, including but not limited to +      communication on electronic mailing lists, source code control systems, +      and issue tracking systems that are managed by, or on behalf of, the +      Licensor for the purpose of discussing and improving the Work, but +      excluding communication that is conspicuously marked or otherwise +      designated in writing by the copyright owner as "Not a Contribution." + +      "Contributor" shall mean Licensor and any individual or Legal Entity +      on behalf of whom a Contribution has been received by Licensor and +      subsequently incorporated within the Work. + +   2. Grant of Copyright License. Subject to the terms and conditions of +      this License, each Contributor hereby grants to You a perpetual, +      worldwide, non-exclusive, no-charge, royalty-free, irrevocable +      copyright license to reproduce, prepare Derivative Works of, +      publicly display, publicly perform, sublicense, and distribute the +      Work and such Derivative Works in Source or Object form. + +   3. Grant of Patent License. Subject to the terms and conditions of +      this License, each Contributor hereby grants to You a perpetual, +      worldwide, non-exclusive, no-charge, royalty-free, irrevocable +      (except as stated in this section) patent license to make, have made, +      use, offer to sell, sell, import, and otherwise transfer the Work, +      where such license applies only to those patent claims licensable +      by such Contributor that are necessarily infringed by their +      Contribution(s) alone or by combination of their Contribution(s) +      with the Work to which such Contribution(s) was submitted. If You +      institute patent litigation against any entity (including a +      cross-claim or counterclaim in a lawsuit) alleging that the Work +      or a Contribution incorporated within the Work constitutes direct +      or contributory patent infringement, then any patent licenses +      granted to You under this License for that Work shall terminate +      as of the date such litigation is filed. + +   4. Redistribution. You may reproduce and distribute copies of the +      Work or Derivative Works thereof in any medium, with or without +      modifications, and in Source or Object form, provided that You +      meet the following conditions: + +      (a) You must give any other recipients of the Work or +          Derivative Works a copy of this License; and + +      (b) You must cause any modified files to carry prominent notices +          stating that You changed the files; and + +      (c) You must retain, in the Source form of any Derivative Works +          that You distribute, all copyright, patent, trademark, and +          attribution notices from the Source form of the Work, +          excluding those notices that do not pertain to any part of +          the Derivative Works; and + +      (d) If the Work includes a "NOTICE" text file as part of its +          distribution, then any Derivative Works that You distribute must +          include a readable copy of the attribution notices contained +          within such NOTICE file, excluding those notices that do not +          pertain to any part of the Derivative Works, in at least one +          of the following places: within a NOTICE text file distributed +          as part of the Derivative Works; within the Source form or +          documentation, if provided along with the Derivative Works; or, +          within a display generated by the Derivative Works, if and +          wherever such third-party notices normally appear. The contents +          of the NOTICE file are for informational purposes only and +          do not modify the License. You may add Your own attribution +          notices within Derivative Works that You distribute, alongside +          or as an addendum to the NOTICE text from the Work, provided +          that such additional attribution notices cannot be construed +          as modifying the License. + +      You may add Your own copyright statement to Your modifications and +      may provide additional or different license terms and conditions +      for use, reproduction, or distribution of Your modifications, or +      for any such Derivative Works as a whole, provided Your use, +      reproduction, and distribution of the Work otherwise complies with +      the conditions stated in this License. + +   5. Submission of Contributions. Unless You explicitly state otherwise, +      any Contribution intentionally submitted for inclusion in the Work +      by You to the Licensor shall be under the terms and conditions of +      this License, without any additional terms or conditions. +      Notwithstanding the above, nothing herein shall supersede or modify +      the terms of any separate license agreement you may have executed +      with Licensor regarding such Contributions. + +   6. Trademarks. This License does not grant permission to use the trade +      names, trademarks, service marks, or product names of the Licensor, +      except as required for reasonable and customary use in describing the +      origin of the Work and reproducing the content of the NOTICE file. + +   7. Disclaimer of Warranty. Unless required by applicable law or +      agreed to in writing, Licensor provides the Work (and each +      Contributor provides its Contributions) on an "AS IS" BASIS, +      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +      implied, including, without limitation, any warranties or conditions +      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +      PARTICULAR PURPOSE. You are solely responsible for determining the +      appropriateness of using or redistributing the Work and assume any +      risks associated with Your exercise of permissions under this License. + +   8. Limitation of Liability. In no event and under no legal theory, +      whether in tort (including negligence), contract, or otherwise, +      unless required by applicable law (such as deliberate and grossly +      negligent acts) or agreed to in writing, shall any Contributor be +      liable to You for damages, including any direct, indirect, special, +      incidental, or consequential damages of any character arising as a +      result of this License or out of the use or inability to use the +      Work (including but not limited to damages for loss of goodwill, +      work stoppage, computer failure or malfunction, or any and all +      other commercial damages or losses), even if such Contributor +      has been advised of the possibility of such damages. + +   9. Accepting Warranty or Additional Liability. While redistributing +      the Work or Derivative Works thereof, You may choose to offer, +      and charge a fee for, acceptance of support, warranty, indemnity, +      or other liability obligations and/or rights consistent with this +      License. However, in accepting such obligations, You may act only +      on Your own behalf and on Your sole responsibility, not on behalf +      of any other Contributor, and only if You agree to indemnify, +      defend, and hold each Contributor harmless for any liability +      incurred by, or claims asserted against, such Contributor by reason +      of your accepting any such warranty or additional liability. + +   END OF TERMS AND CONDITIONS + +   APPENDIX: How to apply the Apache License to your work. + +      To apply the Apache License to your work, attach the following +      boilerplate notice, with the fields enclosed by brackets "[]" +      replaced with your own identifying information. (Don't include +      the brackets!)  The text should be enclosed in the appropriate +      comment syntax for the file format. We also recommend that a +      file or class name and description of purpose be included on the +      same "printed page" as the copyright notice for easier +      identification within third-party archives. + +   Copyright [yyyy] [name of copyright owner] + +   Licensed under the Apache License, Version 2.0 (the "License"); +   you may not use this file except in compliance with the License. +   You may obtain a copy of the License at + +       http://www.apache.org/licenses/LICENSE-2.0 + +   Unless required by applicable law or agreed to in writing, software +   distributed under the License is distributed on an "AS IS" BASIS, +   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +   See the License for the specific language governing permissions and +   limitations under the License. + diff --git a/puppet/modules/ntp/Modulefile b/puppet/modules/ntp/Modulefile new file mode 100644 index 00000000..9610ef67 --- /dev/null +++ b/puppet/modules/ntp/Modulefile @@ -0,0 +1,11 @@ +name    'puppetlabs-ntp' +version '2.0.0-rc1' +source 'git://github.com/puppetlabs/puppetlabs-ntp' +author 'Puppet Labs' +license 'Apache Version 2.0' +summary 'NTP Module' +description 'NTP Module for Debian, Ubuntu, CentOS, RHEL, OEL, Fedora, FreeBSD, ArchLinux and Gentoo.' +project_page 'http://github.com/puppetlabs/puppetlabs-ntp' + +## Add dependencies, if any: +dependency 'puppetlabs/stdlib', '>= 0.1.6' diff --git a/puppet/modules/ntp/README.markdown b/puppet/modules/ntp/README.markdown new file mode 100644 index 00000000..3aedd47a --- /dev/null +++ b/puppet/modules/ntp/README.markdown @@ -0,0 +1,215 @@ +#ntp + +####Table of Contents + +1. [Overview](#overview) +2. [Module Description - What the module does and why it is useful](#module-description) +3. [Setup - The basics of getting started with ntp](#setup) +    * [What ntp affects](#what-ntp-affects) +    * [Setup requirements](#setup-requirements) +    * [Beginning with ntp](#beginning-with-ntp) +4. [Usage - Configuration options and additional functionality](#usage) +5. [Reference - An under-the-hood peek at what the module is doing and how](#reference) +5. [Limitations - OS compatibility, etc.](#limitations) +6. [Development - Guide for contributing to the module](#development) + +##Overview + +The NTP module installs, configures, and manages the ntp service. + +##Module Description + +The NTP module handles running NTP across a range of operating systems and +distributions.  Where possible we use the upstream ntp templates so that the +results closely match what you'd get if you modified the package default conf +files. + +##Setup + +###What ntp affects + +* ntp package. +* ntp configuration file. +* ntp service. + +###Beginning with ntp + +include '::ntp' is enough to get you up and running.  If you wish to pass in +parameters like which servers to use then you can use: + +```puppet +class { '::ntp': +  servers => [ 'ntp1.corp.com', 'ntp2.corp.com' ], +} +``` + +##Usage + +All interaction with the ntp module can do be done through the main ntp class. +This means you can simply toggle the options in the ntp class to get at the +full functionality. + +###I just want NTP, what's the minimum I need? + +```puppet +include '::ntp' +``` + +###I just want to tweak the servers, nothing else. + +```puppet +class { '::ntp': +  servers => [ 'ntp1.corp.com', 'ntp2.corp.com' ], +} +``` + +###I'd like to make sure I restrict who can connect as well. + +```puppet +class { '::ntp': +  servers  => [ 'ntp1.corp.com', 'ntp2.corp.com' ], +  restrict => 'restrict 127.0.0.1', +} +``` + +###I'd like to opt out of having the service controlled, we use another tool for that. + +```puppet +class { '::ntp': +  servers        => [ 'ntp1.corp.com', 'ntp2.corp.com' ], +  restrict       => 'restrict 127.0.0.1', +  manage_service => false, +} +``` + +###Looks great!  But I'd like a different template, we need to do something unique here. + +```puppet +class { '::ntp': +  servers         => [ 'ntp1.corp.com', 'ntp2.corp.com' ], +  restrict        => 'restrict 127.0.0.1', +  manage_service  => false, +  config_template => 'different/module/custom.template.erb', +} +``` + +##Reference + +###Classes + +* ntp: Main class, includes all the rest. +* ntp::install: Handles the packages. +* ntp::config: Handles the configuration file. +* ntp::service: Handles the service. + +###Parameters + +The following parameters are available in the ntp module + +####`autoupdate` + +Deprecated: This parameter previously determined if the ntp module should be +automatically updated to the latest version available.  Replaced by package\_ +ensure. + +####`config` + +This sets the file to write ntp configuration into. + +####`config_template` + +This determines which template puppet should use for the ntp configuration. + +####`driftfile` + +This sets the location of the driftfile for ntp. + +####`keys_controlkey` + +Which of the keys is used as the control key. + +####`keys_enable` + +Should the ntp keys functionality be enabled. + +####`keys_file` + +Location of the keys file. + +####`keys_requestkey` + +Which of the keys is used as the request key. + +####`package_ensure` + +This can be set to 'present' or 'latest' or a specific version to choose the +ntp package to be installed. + +####`package_name` + +This determines the name of the package to install. + +####`panic` + +This determines if ntp should 'panic' in the event of a very large clock skew. +We set this to false if you're on a virtual machine by default as they don't +do a great job with keeping time. + +####`preferred_servers` + +List of ntp servers to prefer.  Will append prefer for any server in this list +that also appears in the servers list. + +####`restrict` + +This sets the restrict options in the ntp configuration. + +####`servers` + +This selects the servers to use for ntp peers. + +####`service_enable` + +This determines if the service should be enabled at boot. + +####`service_ensure` + +This determines if the service should be running or not. + +####`service_manage` + +This selects if puppet should manage the service in the first place. + +####`service_name` + +This selects the name of the ntp service for puppet to manage. + + +##Limitations + +This module has been built on and tested against Puppet 2.7 and higher. + +The module has been tested on: + +* RedHat Enterprise Linux 5/6 +* Debian 6/7 +* CentOS 5/6 +* Ubuntu 12.04 +* Gentoo +* Arch Linux +* FreeBSD + +Testing on other platforms has been light and cannot be guaranteed.  + +##Development + +Puppet Labs modules on the Puppet Forge are open projects, and community +contributions are essential for keeping them great. We can’t access the +huge number of platforms and myriad of hardware, software, and deployment +configurations that Puppet is intended to serve. + +We want to keep it as easy as possible to contribute changes so that our +modules work in your environment. There are a few guidelines that we need +contributors to follow so that we can have a chance of keeping on top of things. + +You can read the complete module contribution guide [on the Puppet Labs wiki.](http://projects.puppetlabs.com/projects/module-site/wiki/Module_contributing) diff --git a/puppet/modules/ntp/Rakefile b/puppet/modules/ntp/Rakefile new file mode 100644 index 00000000..bb60173e --- /dev/null +++ b/puppet/modules/ntp/Rakefile @@ -0,0 +1,2 @@ +require 'puppetlabs_spec_helper/rake_tasks' +require 'rspec-system/rake_task' diff --git a/puppet/modules/ntp/manifests/config.pp b/puppet/modules/ntp/manifests/config.pp new file mode 100644 index 00000000..1c8963dc --- /dev/null +++ b/puppet/modules/ntp/manifests/config.pp @@ -0,0 +1,23 @@ +# +class ntp::config inherits ntp { + +  if $keys_enable { +    $directory = dirname($keys_file) +    file { $directory: +      ensure  => directory, +      owner   => 0, +      group   => 0, +      mode    => '0755', +      recurse => true, +    } +  } + +  file { $config: +    ensure  => file, +    owner   => 0, +    group   => 0, +    mode    => '0644', +    content => template($config_template), +  } + +} diff --git a/puppet/modules/ntp/manifests/init.pp b/puppet/modules/ntp/manifests/init.pp new file mode 100644 index 00000000..be951187 --- /dev/null +++ b/puppet/modules/ntp/manifests/init.pp @@ -0,0 +1,58 @@ +class ntp ( +  $autoupdate        = $ntp::params::autoupdate, +  $config            = $ntp::params::config, +  $config_template   = $ntp::params::config_template, +  $driftfile         = $ntp::params::driftfile, +  $keys_enable       = $ntp::params::keys_enable, +  $keys_file         = $ntp::params::keys_file, +  $keys_controlkey   = $ntp::params::keys_controlkey, +  $keys_requestkey   = $ntp::params::keys_requestkey, +  $keys_trusted      = $ntp::params::keys_trusted, +  $package_ensure    = $ntp::params::package_ensure, +  $package_name      = $ntp::params::package_name, +  $panic             = $ntp::params::panic, +  $preferred_servers = $ntp::params::preferred_servers, +  $restrict          = $ntp::params::restrict, +  $servers           = $ntp::params::servers, +  $service_enable    = $ntp::params::service_enable, +  $service_ensure    = $ntp::params::service_ensure, +  $service_manage    = $ntp::params::service_manage, +  $service_name      = $ntp::params::service_name, +) inherits ntp::params { + +  validate_absolute_path($config) +  validate_string($config_template) +  validate_absolute_path($driftfile) +  validate_bool($keys_enable) +  validate_re($keys_controlkey, ['^\d+$', '']) +  validate_re($keys_requestkey, ['^\d+$', '']) +  validate_array($keys_trusted) +  validate_string($package_ensure) +  validate_array($package_name) +  validate_bool($panic) +  validate_array($preferred_servers) +  validate_array($restrict) +  validate_array($servers) +  validate_bool($service_enable) +  validate_string($service_ensure) +  validate_bool($service_manage) +  validate_string($service_name) + +  if $autoupdate { +    notice('autoupdate parameter has been deprecated and replaced with package_ensure.  Set this to latest for the same behavior as autoupdate => true.') +  } + +  include '::ntp::install' +  include '::ntp::config' +  include '::ntp::service' + +  # Anchor this as per #8040 - this ensures that classes won't float off and +  # mess everything up.  You can read about this at: +  # http://docs.puppetlabs.com/puppet/2.7/reference/lang_containment.html#known-issues +  anchor { 'ntp::begin': } +  anchor { 'ntp::end': } + +  Anchor['ntp::begin'] -> Class['::ntp::install'] -> Class['::ntp::config'] +    ~> Class['::ntp::service'] -> Anchor['ntp::end'] + +} diff --git a/puppet/modules/ntp/manifests/install.pp b/puppet/modules/ntp/manifests/install.pp new file mode 100644 index 00000000..098949c3 --- /dev/null +++ b/puppet/modules/ntp/manifests/install.pp @@ -0,0 +1,9 @@ +# +class ntp::install inherits ntp { + +  package { 'ntp': +    ensure => $package_ensure, +    name   => $package_name, +  } + +} diff --git a/puppet/modules/ntp/manifests/params.pp b/puppet/modules/ntp/manifests/params.pp new file mode 100644 index 00000000..10a4fb2b --- /dev/null +++ b/puppet/modules/ntp/manifests/params.pp @@ -0,0 +1,116 @@ +class ntp::params { + +  $autoupdate        = false +  $config_template   = 'ntp/ntp.conf.erb' +  $keys_enable       = false +  $keys_controlkey   = '' +  $keys_requestkey   = '' +  $keys_trusted      = [] +  $package_ensure    = 'present' +  $preferred_servers = [] +  $restrict          = [ +    'restrict default kod nomodify notrap nopeer noquery', +    'restrict -6 default kod nomodify notrap nopeer noquery', +    'restrict 127.0.0.1', +    'restrict -6 ::1', +  ] +  $service_enable    = true +  $service_ensure    = 'running' +  $service_manage    = true + +  # On virtual machines allow large clock skews. +  $panic = str2bool($::is_virtual) ? { +    true    => false, +    default => true, +  } + +  case $::osfamily { +    'Debian': { +      $config          = '/etc/ntp.conf' +      $keys_file       = '/etc/ntp/keys' +      $driftfile       = '/var/lib/ntp/drift' +      $package_name    = [ 'ntp' ] +      $service_name    = 'ntp' +      $servers         = [ +        '0.debian.pool.ntp.org iburst', +        '1.debian.pool.ntp.org iburst', +        '2.debian.pool.ntp.org iburst', +        '3.debian.pool.ntp.org iburst', +      ] +    } +    'RedHat': { +      $config          = '/etc/ntp.conf' +      $driftfile       = '/var/lib/ntp/drift' +      $keys_file       = '/etc/ntp/keys' +      $package_name    = [ 'ntp' ] +      $service_name    = 'ntpd' +      $servers         = [ +        '0.centos.pool.ntp.org', +        '1.centos.pool.ntp.org', +        '2.centos.pool.ntp.org', +      ] +    } +    'SuSE': { +      $config          = '/etc/ntp.conf' +      $driftfile       = '/var/lib/ntp/drift/ntp.drift' +      $keys_file       = '/etc/ntp/keys' +      $package_name    = [ 'ntp' ] +      $service_name    = 'ntp' +      $servers         = [ +        '0.opensuse.pool.ntp.org', +        '1.opensuse.pool.ntp.org', +        '2.opensuse.pool.ntp.org', +        '3.opensuse.pool.ntp.org', +      ] +    } +    'FreeBSD': { +      $config          = '/etc/ntp.conf' +      $driftfile       = '/var/db/ntpd.drift' +      $keys_file       = '/etc/ntp/keys' +      $package_name    = ['net/ntp'] +      $service_name    = 'ntpd' +      $servers         = [ +        '0.freebsd.pool.ntp.org iburst maxpoll 9', +        '1.freebsd.pool.ntp.org iburst maxpoll 9', +        '2.freebsd.pool.ntp.org iburst maxpoll 9', +        '3.freebsd.pool.ntp.org iburst maxpoll 9', +      ] +    } +    'Archlinux': { +      $config          = '/etc/ntp.conf' +      $driftfile       = '/var/lib/ntp/drift' +      $keys_file       = '/etc/ntp/keys' +      $package_name    = [ 'ntp' ] +      $service_name    = 'ntpd' +      $servers         = [ +        '0.pool.ntp.org', +        '1.pool.ntp.org', +        '2.pool.ntp.org', +      ] +    } +    'Linux': { +      # Account for distributions that don't have $::osfamily specific settings. +      case $::operatingsystem { +        'Gentoo': { +          $config          = '/etc/ntp.conf' +          $driftfile       = '/var/lib/ntp/drift' +          $keys_file       = '/etc/ntp/keys' +          $package_name    = ['net-misc/ntp'] +          $service_name    = 'ntpd' +          $servers         = [ +            '0.gentoo.pool.ntp.org', +            '1.gentoo.pool.ntp.org', +            '2.gentoo.pool.ntp.org', +            '3.gentoo.pool.ntp.org', +          ] +        } +        default: { +          fail("The ${module_name} module is not supported on an ${::operatingsystem} distribution.") +        } +      } +    } +    default: { +      fail("The ${module_name} module is not supported on an ${::osfamily} based system.") +    } +  } +} diff --git a/puppet/modules/ntp/manifests/service.pp b/puppet/modules/ntp/manifests/service.pp new file mode 100644 index 00000000..3f1ada0b --- /dev/null +++ b/puppet/modules/ntp/manifests/service.pp @@ -0,0 +1,18 @@ +# +class ntp::service inherits ntp { + +  if ! ($service_ensure in [ 'running', 'stopped' ]) { +    fail('service_ensure parameter must be running or stopped') +  } + +  if $service_manage == true { +    service { 'ntp': +      ensure     => $service_ensure, +      enable     => $service_enable, +      name       => $service_name, +      hasstatus  => true, +      hasrestart => true, +    } +  } + +} diff --git a/puppet/modules/ntp/spec/classes/ntp_spec.rb b/puppet/modules/ntp/spec/classes/ntp_spec.rb new file mode 100644 index 00000000..6c636f40 --- /dev/null +++ b/puppet/modules/ntp/spec/classes/ntp_spec.rb @@ -0,0 +1,261 @@ +require 'spec_helper' + +describe 'ntp' do + +  ['Debian', 'RedHat','SuSE', 'FreeBSD', 'Archlinux', 'Gentoo'].each do |system| +    if system == 'Gentoo' +      let(:facts) {{ :osfamily => 'Linux', :operatingsystem => system }} +    else +      let(:facts) {{ :osfamily => system }} +    end + +    it { should include_class('ntp::install') } +    it { should include_class('ntp::config') } +    it { should include_class('ntp::service') } + +    describe 'ntp::config on #{system}' do +      it { should contain_file('/etc/ntp.conf').with_owner('0') } +      it { should contain_file('/etc/ntp.conf').with_group('0') } +      it { should contain_file('/etc/ntp.conf').with_mode('0644') } + +      describe 'allows template to be overridden' do +        let(:params) {{ :config_template => 'my_ntp/ntp.conf.erb' }} +        it { should contain_file('/etc/ntp.conf').with({ +          'content' => /server foobar/}) +        } +      end + +      describe "keys for osfamily #{system}" do +        context "when enabled" do +          let(:params) {{ +            :keys_enable     => true, +            :keys_file       => '/etc/ntp/ntp.keys', +            :keys_trusted    => ['1', '2', '3'], +            :keys_controlkey => '2', +            :keys_requestkey => '3', +          }} + +          it { should contain_file('/etc/ntp').with({ +            'ensure'  => 'directory'}) +          } +          it { should contain_file('/etc/ntp.conf').with({ +            'content' => /trustedkey 1 2 3/}) +          } +          it { should contain_file('/etc/ntp.conf').with({ +            'content' => /controlkey 2/}) +          } +          it { should contain_file('/etc/ntp.conf').with({ +            'content' => /requestkey 3/}) +          } +        end +      end + +      context "when disabled" do +        let(:params) {{ +          :keys_enable     => false, +          :keys_file       => '/etc/ntp/ntp.keys', +          :keys_trusted    => ['1', '2', '3'], +          :keys_controlkey => '2', +          :keys_requestkey => '3', +        }} + +        it { should_not contain_file('/etc/ntp').with({ +          'ensure'  => 'directory'}) +        } +        it { should_not contain_file('/etc/ntp.conf').with({ +          'content' => /trustedkey 1 2 3/}) +        } +        it { should_not contain_file('/etc/ntp.conf').with({ +          'content' => /controlkey 2/}) +        } +        it { should_not contain_file('/etc/ntp.conf').with({ +          'content' => /requestkey 3/}) +        } +      end + +      describe 'preferred servers' do +        context "when set" do +          let(:params) {{ +            :servers           => ['a', 'b', 'c', 'd'], +            :preferred_servers => ['a', 'b'] +          }} + +          it { should contain_file('/etc/ntp.conf').with({ +            'content' => /server a prefer\nserver b prefer\nserver c\nserver d/}) +          } +        end +        context "when not set" do +          let(:params) {{ +            :servers           => ['a', 'b', 'c', 'd'], +            :preferred_servers => [] +          }} + +          it { should_not contain_file('/etc/ntp.conf').with({ +            'content' => /server a prefer/}) +          } +        end +      end + +      describe 'ntp::install on #{system}' do +        let(:params) {{ :package_ensure => 'present', :package_name => ['ntp'], }} + +        it { should contain_package('ntp').with( +          :ensure => 'present', +          :name   => 'ntp' +        )} + +        describe 'should allow package ensure to be overridden' do +          let(:params) {{ :package_ensure => 'latest', :package_name => ['ntp'] }} +          it { should contain_package('ntp').with_ensure('latest') } +        end + +        describe 'should allow the package name to be overridden' do +          let(:params) {{ :package_ensure => 'present', :package_name => ['hambaby'] }} +          it { should contain_package('ntp').with_name('hambaby') } +        end +      end + +      describe 'ntp::service' do +        let(:params) {{ +          :service_manage => true, +          :service_enable => true, +          :service_ensure => 'running', +          :service_name   => 'ntp' +        }} + +        describe 'with defaults' do +          it { should contain_service('ntp').with( +            :enable => true, +            :ensure => 'running', +            :name   => 'ntp' +          )} +        end + +        describe 'service_ensure' do +          describe 'when overridden' do +            let(:params) {{ :service_name => 'ntp', :service_ensure => 'stopped' }} +            it { should contain_service('ntp').with_ensure('stopped') } +          end +        end + +        describe 'service_manage' do +          let(:params) {{ +            :service_manage => false, +            :service_enable => true, +            :service_ensure => 'running', +            :service_name   => 'ntpd', +          }} + +          it 'when set to false' do +            should_not contain_service('ntp').with({ +              'enable' => true, +              'ensure' => 'running', +              'name'   => 'ntpd' +            }) +          end +        end +      end +    end + +    context 'ntp::config' do +      describe "for operating system Gentoo" do +        let(:facts) {{ :operatingsystem => 'Gentoo', +                       :osfamily        => 'Linux' }} + +        it 'uses the NTP pool servers by default' do +          should contain_file('/etc/ntp.conf').with({ +            'content' => /server \d.gentoo.pool.ntp.org/, +          }) +        end +      end +      describe "on osfamily Debian" do +        let(:facts) {{ :osfamily => 'debian' }} + +        it 'uses the debian ntp servers by default' do +          should contain_file('/etc/ntp.conf').with({ +            'content' => /server \d.debian.pool.ntp.org iburst/, +          }) +        end +      end + +      describe "on osfamily RedHat" do +        let(:facts) {{ :osfamily => 'RedHat' }} + +        it 'uses the redhat ntp servers by default' do +          should contain_file('/etc/ntp.conf').with({ +            'content' => /server \d.centos.pool.ntp.org/, +          }) +        end +      end + +      describe "on osfamily SuSE" do +        let(:facts) {{ :osfamily => 'SuSE' }} + +        it 'uses the opensuse ntp servers by default' do +          should contain_file('/etc/ntp.conf').with({ +            'content' => /server \d.opensuse.pool.ntp.org/, +          }) +        end +      end + +      describe "on osfamily FreeBSD" do +        let(:facts) {{ :osfamily => 'FreeBSD' }} + +        it 'uses the freebsd ntp servers by default' do +          should contain_file('/etc/ntp.conf').with({ +            'content' => /server \d.freebsd.pool.ntp.org iburst maxpoll 9/, +          }) +        end +      end + +      describe "on osfamily ArchLinux" do +        let(:facts) {{ :osfamily => 'ArchLinux' }} + +        it 'uses the NTP pool servers by default' do +          should contain_file('/etc/ntp.conf').with({ +            'content' => /server \d.pool.ntp.org/, +          }) +        end +      end + +      describe "for operating system family unsupported" do +        let(:facts) {{ +          :osfamily  => 'unsupported', +        }} + +        it { expect{ subject }.to raise_error( +          /^The ntp module is not supported on an unsupported based system./ +        )} +      end +    end + +    describe 'for virtual machines' do +      let(:facts) {{ :osfamily        => 'Archlinux', +                     :is_virtual      => 'true' }} + +      it 'should not use local clock as a time source' do +        should_not contain_file('/etc/ntp.conf').with({ +          'content' => /server.*127.127.1.0.*fudge.*127.127.1.0 stratum 10/, +        }) +      end + +      it 'allows large clock skews' do +        should contain_file('/etc/ntp.conf').with({ +          'content' => /tinker panic 0/, +        }) +      end +    end + +    describe 'for physical machines' do +      let(:facts) {{ :osfamily        => 'Archlinux', +                     :is_virtual      => 'false' }} + +      it 'disallows large clock skews' do +        should_not contain_file('/etc/ntp.conf').with({ +          'content' => /tinker panic 0/, +        }) +      end +    end +  end + +end diff --git a/puppet/modules/ntp/spec/fixtures/modules/my_ntp/templates/ntp.conf.erb b/puppet/modules/ntp/spec/fixtures/modules/my_ntp/templates/ntp.conf.erb new file mode 100644 index 00000000..40cf67c6 --- /dev/null +++ b/puppet/modules/ntp/spec/fixtures/modules/my_ntp/templates/ntp.conf.erb @@ -0,0 +1,4 @@ +#my uber ntp config +# + +server foobar diff --git a/puppet/modules/ntp/spec/spec.opts b/puppet/modules/ntp/spec/spec.opts new file mode 100644 index 00000000..91cd6427 --- /dev/null +++ b/puppet/modules/ntp/spec/spec.opts @@ -0,0 +1,6 @@ +--format +s +--colour +--loadby +mtime +--backtrace diff --git a/puppet/modules/ntp/spec/spec_helper.rb b/puppet/modules/ntp/spec/spec_helper.rb new file mode 100644 index 00000000..2c6f5664 --- /dev/null +++ b/puppet/modules/ntp/spec/spec_helper.rb @@ -0,0 +1 @@ +require 'puppetlabs_spec_helper/module_spec_helper' diff --git a/puppet/modules/ntp/spec/spec_helper_system.rb b/puppet/modules/ntp/spec/spec_helper_system.rb new file mode 100644 index 00000000..d5208463 --- /dev/null +++ b/puppet/modules/ntp/spec/spec_helper_system.rb @@ -0,0 +1,26 @@ +require 'rspec-system/spec_helper' +require 'rspec-system-puppet/helpers' +require 'rspec-system-serverspec/helpers' +include Serverspec::Helper::RSpecSystem +include Serverspec::Helper::DetectOS +include RSpecSystemPuppet::Helpers + +RSpec.configure do |c| +  # Project root +  proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) + +  # Enable colour +  c.tty = true + +  c.include RSpecSystemPuppet::Helpers + +  # This is where we 'setup' the nodes before running our tests +  c.before :suite do +    # Install puppet +    puppet_install + +    # Install modules and dependencies +    puppet_module_install(:source => proj_root, :module_name => 'ntp') +    shell('puppet module install puppetlabs-stdlib') +  end +end diff --git a/puppet/modules/ntp/spec/system/basic_spec.rb b/puppet/modules/ntp/spec/system/basic_spec.rb new file mode 100644 index 00000000..7b717a04 --- /dev/null +++ b/puppet/modules/ntp/spec/system/basic_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper_system' + +# Here we put the more basic fundamental tests, ultra obvious stuff. +describe "basic tests:" do +  context 'make sure we have copied the module across' do +    # No point diagnosing any more if the module wasn't copied properly +    context shell 'ls /etc/puppet/modules/ntp' do +      its(:stdout) { should =~ /Modulefile/ } +      its(:stderr) { should be_empty } +      its(:exit_code) { should be_zero } +    end +  end +end diff --git a/puppet/modules/ntp/spec/system/class_spec.rb b/puppet/modules/ntp/spec/system/class_spec.rb new file mode 100644 index 00000000..49dfc641 --- /dev/null +++ b/puppet/modules/ntp/spec/system/class_spec.rb @@ -0,0 +1,39 @@ +require 'spec_helper_system' + +describe "ntp class:" do +  context 'should run successfully' do +    pp = "class { 'ntp': }" + +    context puppet_apply(pp) do +      its(:stderr) { should be_empty } +      its(:exit_code) { should_not == 1 } +      its(:refresh) { should be_nil } +      its(:stderr) { should be_empty } +      its(:exit_code) { should be_zero } +    end +  end + +  context 'service_ensure => stopped:' do +    pp = "class { 'ntp': service_ensure => stopped }" + +    context puppet_apply(pp) do +      its(:stderr) { should be_empty } +      its(:exit_code) { should_not == 1 } +      its(:refresh) { should be_nil } +      its(:stderr) { should be_empty } +      its(:exit_code) { should be_zero } +    end +  end + +  context 'service_ensure => running:' do +    pp = "class { 'ntp': service_ensure => running }" + +    context puppet_apply(pp) do |r| +      its(:stderr) { should be_empty } +      its(:exit_code) { should_not == 1 } +      its(:refresh) { should be_nil } +      its(:stderr) { should be_empty } +      its(:exit_code) { should be_zero } +    end +  end +end diff --git a/puppet/modules/ntp/spec/system/ntp_config_spec.rb b/puppet/modules/ntp/spec/system/ntp_config_spec.rb new file mode 100644 index 00000000..194cdf10 --- /dev/null +++ b/puppet/modules/ntp/spec/system/ntp_config_spec.rb @@ -0,0 +1,35 @@ +require 'spec_helper_system' + +describe 'ntp::config class' do +  let(:os) { +    node.facts['osfamily'] +  } + +  puppet_apply(%{ +    class { 'ntp': } +  }) + +  case node.facts['osfamily'] +  when 'FreeBSD' +    line = '0.freebsd.pool.ntp.org iburst maxpoll 9' +  when 'Debian' +    line = '0.debian.pool.ntp.org iburst' +  when 'RedHat' +    line = '0.centos.pool.ntp.org' +  when 'SuSE' +    line = '0.opensuse.pool.ntp.org' +  when 'Linux' +    case node.facts['operatingsystem'] +    when 'ArchLinux' +      line = '0.pool.ntp.org' +    when 'Gentoo' +      line = '0.gentoo.pool.ntp.org' +    end +  end + +  describe file('/etc/ntp.conf') do +    it { should be_file } +    it { should contain line } +  end + +end diff --git a/puppet/modules/ntp/spec/system/ntp_install_spec.rb b/puppet/modules/ntp/spec/system/ntp_install_spec.rb new file mode 100644 index 00000000..39759c5e --- /dev/null +++ b/puppet/modules/ntp/spec/system/ntp_install_spec.rb @@ -0,0 +1,31 @@ +require 'spec_helper_system' + + +describe 'ntp::install class' do +  let(:os) { +    node.facts['osfamily'] +  } + +  case node.facts['osfamily'] +  when 'FreeBSD' +    packagename = 'net/ntp' +  when 'Linux' +    case node.facts['operatingsystem'] +    when 'ArchLinux' +      packagename = 'ntp' +    when 'Gentoo' +      packagename = 'net-misc/ntp' +    end +  else +    packagename = 'ntp' +  end + +  puppet_apply(%{ +    class { 'ntp': } +  }) + +  describe package(packagename) do +    it { should be_installed } +  end + +end diff --git a/puppet/modules/ntp/spec/system/ntp_service_spec.rb b/puppet/modules/ntp/spec/system/ntp_service_spec.rb new file mode 100644 index 00000000..b97e2a4e --- /dev/null +++ b/puppet/modules/ntp/spec/system/ntp_service_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper_system' + + +describe 'ntp::service class' do +  let(:os) { +    node.facts['osfamily'] +  } + +  case node.facts['osfamily'] +  when 'RedHat', 'FreeBSD', 'Linux' +    servicename = 'ntpd' +  else +    servicename = 'ntp' +  end + +  puppet_apply(%{ +    class { 'ntp': } +  }) + +  describe service(servicename) do +    it { should be_enabled } +    it { should be_running } +  end + +end diff --git a/puppet/modules/ntp/spec/system/preferred_servers_spec.rb b/puppet/modules/ntp/spec/system/preferred_servers_spec.rb new file mode 100644 index 00000000..686861bc --- /dev/null +++ b/puppet/modules/ntp/spec/system/preferred_servers_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper_system' + +describe 'preferred servers' do +  it 'applies cleanly' do +    puppet_apply(%{ +      class { '::ntp': +        servers           => ['a', 'b', 'c', 'd'], +        preferred_servers => ['c', 'd'], +      } +    }) +  end + +  describe file('/etc/ntp.conf') do +    it { should be_file } +    it { should contain 'server a' } +    it { should contain 'server b' } +    it { should contain 'server c prefer' } +    it { should contain 'server d prefer' } +  end +end diff --git a/puppet/modules/ntp/spec/system/restrict_spec.rb b/puppet/modules/ntp/spec/system/restrict_spec.rb new file mode 100644 index 00000000..ae23bc01 --- /dev/null +++ b/puppet/modules/ntp/spec/system/restrict_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper_system' + +describe "ntp class with restrict:" do +  context 'should run successfully' do +    pp = "class { 'ntp': restrict => ['test restrict']}" + +    context puppet_apply(pp) do +      its(:stderr) { should be_empty } +      its(:exit_code) { should_not == 1 } +      its(:refresh) { should be_nil } +      its(:stderr) { should be_empty } +      its(:exit_code) { should be_zero } +    end +  end + +  describe file('/etc/ntp.conf') do +    it { should contain('test restrict') } +  end + +end diff --git a/puppet/modules/ntp/spec/unit/puppet/provider/README.markdown b/puppet/modules/ntp/spec/unit/puppet/provider/README.markdown new file mode 100644 index 00000000..70258502 --- /dev/null +++ b/puppet/modules/ntp/spec/unit/puppet/provider/README.markdown @@ -0,0 +1,4 @@ +Provider Specs +============== + +Define specs for your providers under this directory. diff --git a/puppet/modules/ntp/spec/unit/puppet/type/README.markdown b/puppet/modules/ntp/spec/unit/puppet/type/README.markdown new file mode 100644 index 00000000..1ee19ac8 --- /dev/null +++ b/puppet/modules/ntp/spec/unit/puppet/type/README.markdown @@ -0,0 +1,4 @@ +Resource Type Specs +=================== + +Define specs for your resource types in this directory. diff --git a/puppet/modules/ntp/templates/ntp.conf.erb b/puppet/modules/ntp/templates/ntp.conf.erb new file mode 100644 index 00000000..94b36755 --- /dev/null +++ b/puppet/modules/ntp/templates/ntp.conf.erb @@ -0,0 +1,43 @@ +# ntp.conf: Managed by puppet. +# +<% if @panic == false -%> +# Keep ntpd from panicking in the event of a large clock skew +# when a VM guest is suspended and resumed. +tinker panic 0 +<% end -%> + +<% if @restrict != [] -%> +# Permit time synchronization with our time source, but do not' +# permit the source to query or modify the service on this system.' +<% @restrict.flatten.each do |restrict| -%> +<%= restrict %> +<% end %> +<% end -%> + +# Servers +<% [@servers].flatten.each do |server| -%> +server <%= server %><% if @preferred_servers.include?(server) -%> prefer<% end %> +<% end -%> + +<% if scope.lookupvar('::is_virtual') == "false" -%> +# Undisciplined Local Clock. This is a fake driver intended for backup +# and when no outside source of synchronized time is available.  +server	127.127.1.0	# local clock +fudge	127.127.1.0 stratum 10	 +<% end -%> + +# Driftfile. +driftfile <%= @driftfile %> + +<% if @keys_enable -%> +keys <%= @keys_file %> +<% unless @keys_trusted.empty? -%> +trustedkey <%= @keys_trusted.join(' ') %> +<% end -%> +<% if @keys_requestkey != '' -%> +requestkey <%= @keys_requestkey %> +<% end -%> +<% if @keys_controlkey != '' -%> +controlkey <%= @keys_controlkey %> +<% end -%> +<% end -%> diff --git a/puppet/modules/ntp/tests/init.pp b/puppet/modules/ntp/tests/init.pp new file mode 100644 index 00000000..e6d9b537 --- /dev/null +++ b/puppet/modules/ntp/tests/init.pp @@ -0,0 +1,11 @@ +node default { + +  notify { 'enduser-before': } +  notify { 'enduser-after': } + +  class { 'ntp': +    require => Notify['enduser-before'], +    before  => Notify['enduser-after'], +  } + +} diff --git a/puppet/modules/obfsproxy/files/obfsproxy_init b/puppet/modules/obfsproxy/files/obfsproxy_init new file mode 100755 index 00000000..01c8013a --- /dev/null +++ b/puppet/modules/obfsproxy/files/obfsproxy_init @@ -0,0 +1,93 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides:          obfsproxy daemon +# Required-Start:    $remote_fs $syslog +# Required-Stop:     $remote_fs $syslog +# Default-Start:     2 3 4 5 +# Default-Stop:      0 1 6 +# Short-Description: obfsproxy daemon +# Description:       obfsproxy daemon +### END INIT INFO + +. /lib/lsb/init-functions + +DAEMON=/usr/bin/obfsproxy +NAME=obfsproxy +DESC="obfsproxy daemon" +USER=obfsproxy +DATDIR=/etc/obfsproxy +PIDFILE=/var/run/obfsproxy.pid +CONF=$DATDIR/obfsproxy.conf +LOGFILE=/var/log/obfsproxy.log + +# If the daemon is not there, then exit. +test -x $DAEMON || exit 0 + +if [ -f $CONF ] ; then +  . $CONF +else +  echo "Obfsproxy configuration file is missing, aborting..." +  exit 2 +fi + +DAEMONARGS=" --log-min-severity=$LOG --log-file=$LOGFILE --data-dir=$DATDIR \ +            $TRANSPORT $PARAM --dest=$DEST_IP:$DEST_PORT server $BINDADDR:$PORT" + +start_obfsproxy() { +  start-stop-daemon --start --quiet --oknodo -m --pidfile $PIDFILE \ +		-b -c $USER --startas $DAEMON --$DAEMONARGS +} + +stop_obfsproxy() { +  start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE +} + +status_obfsproxy() { +  status_of_proc -p $PIDFILE $DAEMON $NAME +} + +case $1 in + start) +  if [ -e $PIDFILE ]; then +   status_obfsproxy +   if [ $? = "0" ]; then +    exit +   fi +  fi +  log_begin_msg "Starting $DESC" +  start_obfsproxy +  log_end_msg $? +  ;; + stop) +  if [ -e $PIDFILE ]; then +   status_obfsproxy +   if [ $? = "0" ]; then +     log_begin_msg "Stopping $DESC" +     stop_obfsproxy +     rm -f $PIDFILE +     log_end_msg $? +   fi +  else +     status_obfsproxy +  fi +  ;; + restart) +  $0 stop && sleep 2 && $0 start +  ;; + status) +  status_obfsproxy +  ;; + reload) +  if [ -e $PIDFILE ]; then +   start-stop-daemon --stop --signal USR1 --quiet --pidfile $PIDFILE --name $NAME +   log_success_msg "$DESC reloaded successfully" +  else +   log_failure_msg "$PIDFILE does not exist" +  fi +  ;; + *) +  echo "Usage: $0 {start|stop|restart|reload|status}" +  exit 2 +  ;; +esac diff --git a/puppet/modules/obfsproxy/files/obfsproxy_logrotate b/puppet/modules/obfsproxy/files/obfsproxy_logrotate new file mode 100644 index 00000000..e5679d0c --- /dev/null +++ b/puppet/modules/obfsproxy/files/obfsproxy_logrotate @@ -0,0 +1,14 @@ +/var/log/obfsproxy.log { +  daily +  missingok +  rotate 3 +  compress +  delaycompress +  notifempty +  create 600 obfsproxy obfsproxy +  postrotate +    if [ -f /var/run/obfsproxy.pid ]; then +      /etc/init.d/obfsproxy restart > /dev/null +    fi +  endscript +} diff --git a/puppet/modules/obfsproxy/manifests/init.pp b/puppet/modules/obfsproxy/manifests/init.pp new file mode 100644 index 00000000..6a3d2c72 --- /dev/null +++ b/puppet/modules/obfsproxy/manifests/init.pp @@ -0,0 +1,86 @@ +# deploy obfsproxy service +class obfsproxy ( +  $transport, +  $bind_address, +  $port, +  $param, +  $dest_ip, +  $dest_port, +  $log_level = 'info' +){ + +  $user = 'obfsproxy' +  $conf = '/etc/obfsproxy/obfsproxy.conf' + +  user { $user: +    ensure => present, +    system => true, +    gid    => $user, +  } + +  group { $user: +    ensure => present, +    system => true, +  } + +  file { '/etc/init.d/obfsproxy': +    ensure  => present, +    path    => '/etc/init.d/obfsproxy', +    source  => 'puppet:///modules/obfsproxy/obfsproxy_init', +    owner   => 'root', +    group   => 'root', +    mode    => '0750', +    require => File[$conf], +  } + +  file { $conf : +    ensure  => present, +    path    => $conf, +    owner   => 'root', +    group   => 'root', +    mode    => '0600', +    content => template('obfsproxy/etc_conf.erb'), +  } + +  file { '/etc/obfsproxy': +    ensure  => directory, +    owner   => $user, +    group   => $user, +    mode    => '0700', +    require => User[$user], +  } + +  file { '/var/log/obfsproxy.log': +    ensure  => present, +    owner   => $user, +    group   => $user, +    mode    => '0640', +    require => User[$user], +  } + +  file { '/etc/logrotate.d/obfsproxy': +    ensure  => present, +    source  => 'puppet:///modules/obfsproxy/obfsproxy_logrotate', +    owner   => 'root', +    group   => 'root', +    mode    => '0644', +    require => File['/var/log/obfsproxy.log'], +  } + +  package { 'obfsproxy': +    ensure  => present +  } + +  service { 'obfsproxy': +    ensure    => running, +    subscribe => File[$conf], +    require   => [ +      Package['obfsproxy'], +      File['/etc/init.d/obfsproxy'], +      User[$user], +      Group[$user]] +  } + + +} + diff --git a/puppet/modules/obfsproxy/templates/etc_conf.erb b/puppet/modules/obfsproxy/templates/etc_conf.erb new file mode 100644 index 00000000..8959ef78 --- /dev/null +++ b/puppet/modules/obfsproxy/templates/etc_conf.erb @@ -0,0 +1,11 @@ +TRANSPORT=<%= @transport %> +PORT=<%= @port %> +DEST_IP=<%= @dest_ip %> +DEST_PORT=<%= @dest_port %> +<% if @transport == "scramblesuit" -%> +PARAM=--password=<%= @param %> +<% else -%> +PARAM=<%= @param %> +<% end -%> +LOG=<%= @log_level %> +BINDADDR=<%= @bind_address %> diff --git a/puppet/modules/opendkim/manifests/init.pp b/puppet/modules/opendkim/manifests/init.pp new file mode 100644 index 00000000..4d4c5312 --- /dev/null +++ b/puppet/modules/opendkim/manifests/init.pp @@ -0,0 +1,67 @@ +# +# I am not sure about what issues might arise with DKIM key sizes +# larger than 2048. It might or might not be supported. See: +# http://dkim.org/specs/rfc4871-dkimbase.html#rfc.section.3.3.3 +# +class opendkim { + +  $domain_hash = hiera('domain') +  $domain      = $domain_hash['full_suffix'] +  $mx          = hiera('mx') +  $dkim        = $mx['dkim'] +  $selector    = $dkim['selector'] +  $dkim_cert   = $dkim['public_key'] +  $dkim_key    = $dkim['private_key'] + +  ensure_packages(['opendkim', 'libvbr2']) + +  # postfix user needs to be in the opendkim group +  # in order to access the opendkim socket located at: +  # local:/var/run/opendkim/opendkim.sock +  user { 'postfix': +    groups  => 'opendkim', +    require => Package['opendkim']; +  } + +  service { 'opendkim': +    ensure     => running, +    enable     => true, +    hasstatus  => true, +    hasrestart => true, +    subscribe  => File[$dkim_key]; +  } + +  file { +    '/etc/opendkim.conf': +      ensure  => file, +      content => template('opendkim/opendkim.conf'), +      mode    => '0644', +      owner   => root, +      group   => root, +      notify  => Service['opendkim'], +      require => Package['opendkim']; + +    '/etc/default/opendkim.conf': +      ensure  => file, +      content => 'SOCKET="inet:8891@localhost" # listen on loopback on port 8891', +      mode    => '0644', +      owner   => root, +      group   => root, +      notify  => Service['opendkim'], +      require => Package['opendkim']; + +    $dkim_key: +      ensure  => file, +      mode    => '0600', +      owner   => 'opendkim', +      group   => 'opendkim', +      require => Package['opendkim']; + +    $dkim_cert: +      ensure  => file, +      mode    => '0600', +      owner   => 'opendkim', +      group   => 'opendkim', +      require => Package['opendkim']; +  } +} diff --git a/puppet/modules/opendkim/templates/opendkim.conf b/puppet/modules/opendkim/templates/opendkim.conf new file mode 100644 index 00000000..5a948229 --- /dev/null +++ b/puppet/modules/opendkim/templates/opendkim.conf @@ -0,0 +1,45 @@ +# This is a basic configuration that can easily be adapted to suit a standard +# installation. For more advanced options, see opendkim.conf(5) and/or +# /usr/share/doc/opendkim/examples/opendkim.conf.sample. + +# Log to syslog +Syslog                  yes +SyslogSuccess           yes +LogWhy                  no +# Required to use local socket with MTAs that access the socket as a non- +# privileged user (e.g. Postfix) +UMask                   002 + +Domain                  <%= @domain %> +SubDomains              yes + +# set internal hosts to all the known hosts, like mydomains? + +# can we generate a larger key and get it in dns? +KeyFile                 <%= @dkim_key %> + +Selector                <%= @selector %> + +# Commonly-used options; the commented-out versions show the defaults. +Canonicalization        relaxed +#Mode                   sv +#ADSPDiscard            no + +SignatureAlgorithm      rsa-sha256 + +# Always oversign From (sign using actual From and a null From to prevent +# malicious signatures header fields (From and/or others) between the signer +# and the verifier.  From is oversigned by default in the Debian pacakge +# because it is often the identity key used by reputation systems and thus +# somewhat security sensitive. +OversignHeaders         From + +# List domains to use for RFC 6541 DKIM Authorized Third-Party Signatures +# (ATPS) (experimental) + +#ATPSDomains            example.com + +RemoveOldSignatures     yes + +Mode                    sv +BaseDirectory           /var/tmp diff --git a/puppet/modules/openvpn/.fixtures.yml b/puppet/modules/openvpn/.fixtures.yml new file mode 100644 index 00000000..1125ecca --- /dev/null +++ b/puppet/modules/openvpn/.fixtures.yml @@ -0,0 +1,6 @@ +fixtures: +  repositories: +    concat: git://github.com/ripienaar/puppet-concat.git +  symlinks: +    openvpn: "#{source_dir}" + diff --git a/puppet/modules/openvpn/.gitignore b/puppet/modules/openvpn/.gitignore new file mode 100644 index 00000000..6fd248b3 --- /dev/null +++ b/puppet/modules/openvpn/.gitignore @@ -0,0 +1,3 @@ +pkg +spec/fixtures +.vagrant diff --git a/puppet/modules/openvpn/.rvmrc b/puppet/modules/openvpn/.rvmrc new file mode 100644 index 00000000..6fbfb7f1 --- /dev/null +++ b/puppet/modules/openvpn/.rvmrc @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# This is an RVM Project .rvmrc file, used to automatically load the ruby +# development environment upon cd'ing into the directory + +# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional, +# Only full ruby name is supported here, for short names use: +#     echo "rvm use 1.9.3" > .rvmrc +environment_id="ruby-1.9.3-p194@puppet" + +# Uncomment the following lines if you want to verify rvm version per project +# rvmrc_rvm_version="1.15.8 (stable)" # 1.10.1 seams as a safe start +# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || { +#   echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading." +#   return 1 +# } + +# First we attempt to load the desired environment directly from the environment +# file. This is very fast and efficient compared to running through the entire +# CLI and selector. If you want feedback on which environment was used then +# insert the word 'use' after --create as this triggers verbose mode. +if [[ -d "${rvm_path:-$HOME/.rvm}/environments" +  && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]] +then +  \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id" +  [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] && +    \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true +  if [[ $- == *i* ]] # check for interactive shells +  then echo "Using: $(tput setaf 2)$GEM_HOME$(tput sgr0)" # show the user the ruby and gemset they are using in green +  else echo "Using: $GEM_HOME" # don't use colors in non-interactive shells +  fi +else +  # If the environment file has not yet been created, use the RVM CLI to select. +  rvm --create use  "$environment_id" || { +    echo "Failed to create RVM environment '${environment_id}'." +    return 1 +  } +fi diff --git a/puppet/modules/openvpn/.travis.yml b/puppet/modules/openvpn/.travis.yml new file mode 100644 index 00000000..da5c389d --- /dev/null +++ b/puppet/modules/openvpn/.travis.yml @@ -0,0 +1,29 @@ +language: ruby +bundler_args: --without development +script: "bundle exec rake spec SPEC_OPTS='--format documentation'" +rvm: +  - 1.8.7 +  - 1.9.3 +  - 2.0.0 +script: +  - "rake lint" +  - "rake spec SPEC_OPTS='--format documentation'" +env: +  - PUPPET_VERSION="~> 2.7.0" +  - PUPPET_VERSION="~> 3.0.0" +  - PUPPET_VERSION="~> 3.1.0" +  - PUPPET_VERSION="~> 3.2.0" +matrix: +  exclude: +    - rvm: 1.9.3 +      env: PUPPET_VERSION="~> 2.7.0" +    - rvm: 2.0.0 +      env: PUPPET_VERSION="~> 2.7.0" +    - rvm: 2.0.0 +      env: PUPPET_VERSION="~> 3.0.0" +    - rvm: 2.0.0 +      env: PUPPET_VERSION="~> 3.1.0" +notifications: +  email: false +  on_success: always +  on_failure: always diff --git a/puppet/modules/openvpn/Gemfile b/puppet/modules/openvpn/Gemfile new file mode 100644 index 00000000..68e10e7d --- /dev/null +++ b/puppet/modules/openvpn/Gemfile @@ -0,0 +1,7 @@ +source :rubygems + +puppetversion = ENV['PUPPET_VERSION'] +gem 'puppet', puppetversion, :require => false +gem 'puppet-lint' +gem 'rspec-puppet' +gem 'puppetlabs_spec_helper' diff --git a/puppet/modules/openvpn/Gemfile.lock b/puppet/modules/openvpn/Gemfile.lock new file mode 100644 index 00000000..9fce3f98 --- /dev/null +++ b/puppet/modules/openvpn/Gemfile.lock @@ -0,0 +1,36 @@ +GEM +  remote: http://rubygems.org/ +  specs: +    diff-lcs (1.1.3) +    facter (1.6.17) +    hiera (1.0.0) +    metaclass (0.0.1) +    mocha (0.13.1) +      metaclass (~> 0.0.1) +    puppet (3.0.2) +      facter (~> 1.6.11) +      hiera (~> 1.0.0) +    puppetlabs_spec_helper (0.4.0) +      mocha (>= 0.10.5) +      rake +      rspec (>= 2.9.0) +      rspec-puppet (>= 0.1.1) +    rake (10.0.3) +    rspec (2.12.0) +      rspec-core (~> 2.12.0) +      rspec-expectations (~> 2.12.0) +      rspec-mocks (~> 2.12.0) +    rspec-core (2.12.2) +    rspec-expectations (2.12.1) +      diff-lcs (~> 1.1.3) +    rspec-mocks (2.12.1) +    rspec-puppet (0.1.5) +      rspec + +PLATFORMS +  ruby + +DEPENDENCIES +  puppet +  puppetlabs_spec_helper +  rspec-puppet diff --git a/puppet/modules/openvpn/LICENSE b/puppet/modules/openvpn/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/puppet/modules/openvpn/LICENSE @@ -0,0 +1,177 @@ + +                                 Apache License +                           Version 2.0, January 2004 +                        http://www.apache.org/licenses/ + +   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +   1. Definitions. + +      "License" shall mean the terms and conditions for use, reproduction, +      and distribution as defined by Sections 1 through 9 of this document. + +      "Licensor" shall mean the copyright owner or entity authorized by +      the copyright owner that is granting the License. + +      "Legal Entity" shall mean the union of the acting entity and all +      other entities that control, are controlled by, or are under common +      control with that entity. For the purposes of this definition, +      "control" means (i) the power, direct or indirect, to cause the +      direction or management of such entity, whether by contract or +      otherwise, or (ii) ownership of fifty percent (50%) or more of the +      outstanding shares, or (iii) beneficial ownership of such entity. + +      "You" (or "Your") shall mean an individual or Legal Entity +      exercising permissions granted by this License. + +      "Source" form shall mean the preferred form for making modifications, +      including but not limited to software source code, documentation +      source, and configuration files. + +      "Object" form shall mean any form resulting from mechanical +      transformation or translation of a Source form, including but +      not limited to compiled object code, generated documentation, +      and conversions to other media types. + +      "Work" shall mean the work of authorship, whether in Source or +      Object form, made available under the License, as indicated by a +      copyright notice that is included in or attached to the work +      (an example is provided in the Appendix below). + +      "Derivative Works" shall mean any work, whether in Source or Object +      form, that is based on (or derived from) the Work and for which the +      editorial revisions, annotations, elaborations, or other modifications +      represent, as a whole, an original work of authorship. For the purposes +      of this License, Derivative Works shall not include works that remain +      separable from, or merely link (or bind by name) to the interfaces of, +      the Work and Derivative Works thereof. + +      "Contribution" shall mean any work of authorship, including +      the original version of the Work and any modifications or additions +      to that Work or Derivative Works thereof, that is intentionally +      submitted to Licensor for inclusion in the Work by the copyright owner +      or by an individual or Legal Entity authorized to submit on behalf of +      the copyright owner. For the purposes of this definition, "submitted" +      means any form of electronic, verbal, or written communication sent +      to the Licensor or its representatives, including but not limited to +      communication on electronic mailing lists, source code control systems, +      and issue tracking systems that are managed by, or on behalf of, the +      Licensor for the purpose of discussing and improving the Work, but +      excluding communication that is conspicuously marked or otherwise +      designated in writing by the copyright owner as "Not a Contribution." + +      "Contributor" shall mean Licensor and any individual or Legal Entity +      on behalf of whom a Contribution has been received by Licensor and +      subsequently incorporated within the Work. + +   2. Grant of Copyright License. Subject to the terms and conditions of +      this License, each Contributor hereby grants to You a perpetual, +      worldwide, non-exclusive, no-charge, royalty-free, irrevocable +      copyright license to reproduce, prepare Derivative Works of, +      publicly display, publicly perform, sublicense, and distribute the +      Work and such Derivative Works in Source or Object form. + +   3. Grant of Patent License. Subject to the terms and conditions of +      this License, each Contributor hereby grants to You a perpetual, +      worldwide, non-exclusive, no-charge, royalty-free, irrevocable +      (except as stated in this section) patent license to make, have made, +      use, offer to sell, sell, import, and otherwise transfer the Work, +      where such license applies only to those patent claims licensable +      by such Contributor that are necessarily infringed by their +      Contribution(s) alone or by combination of their Contribution(s) +      with the Work to which such Contribution(s) was submitted. If You +      institute patent litigation against any entity (including a +      cross-claim or counterclaim in a lawsuit) alleging that the Work +      or a Contribution incorporated within the Work constitutes direct +      or contributory patent infringement, then any patent licenses +      granted to You under this License for that Work shall terminate +      as of the date such litigation is filed. + +   4. Redistribution. You may reproduce and distribute copies of the +      Work or Derivative Works thereof in any medium, with or without +      modifications, and in Source or Object form, provided that You +      meet the following conditions: + +      (a) You must give any other recipients of the Work or +          Derivative Works a copy of this License; and + +      (b) You must cause any modified files to carry prominent notices +          stating that You changed the files; and + +      (c) You must retain, in the Source form of any Derivative Works +          that You distribute, all copyright, patent, trademark, and +          attribution notices from the Source form of the Work, +          excluding those notices that do not pertain to any part of +          the Derivative Works; and + +      (d) If the Work includes a "NOTICE" text file as part of its +          distribution, then any Derivative Works that You distribute must +          include a readable copy of the attribution notices contained +          within such NOTICE file, excluding those notices that do not +          pertain to any part of the Derivative Works, in at least one +          of the following places: within a NOTICE text file distributed +          as part of the Derivative Works; within the Source form or +          documentation, if provided along with the Derivative Works; or, +          within a display generated by the Derivative Works, if and +          wherever such third-party notices normally appear. The contents +          of the NOTICE file are for informational purposes only and +          do not modify the License. You may add Your own attribution +          notices within Derivative Works that You distribute, alongside +          or as an addendum to the NOTICE text from the Work, provided +          that such additional attribution notices cannot be construed +          as modifying the License. + +      You may add Your own copyright statement to Your modifications and +      may provide additional or different license terms and conditions +      for use, reproduction, or distribution of Your modifications, or +      for any such Derivative Works as a whole, provided Your use, +      reproduction, and distribution of the Work otherwise complies with +      the conditions stated in this License. + +   5. Submission of Contributions. Unless You explicitly state otherwise, +      any Contribution intentionally submitted for inclusion in the Work +      by You to the Licensor shall be under the terms and conditions of +      this License, without any additional terms or conditions. +      Notwithstanding the above, nothing herein shall supersede or modify +      the terms of any separate license agreement you may have executed +      with Licensor regarding such Contributions. + +   6. Trademarks. This License does not grant permission to use the trade +      names, trademarks, service marks, or product names of the Licensor, +      except as required for reasonable and customary use in describing the +      origin of the Work and reproducing the content of the NOTICE file. + +   7. Disclaimer of Warranty. Unless required by applicable law or +      agreed to in writing, Licensor provides the Work (and each +      Contributor provides its Contributions) on an "AS IS" BASIS, +      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +      implied, including, without limitation, any warranties or conditions +      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +      PARTICULAR PURPOSE. You are solely responsible for determining the +      appropriateness of using or redistributing the Work and assume any +      risks associated with Your exercise of permissions under this License. + +   8. Limitation of Liability. In no event and under no legal theory, +      whether in tort (including negligence), contract, or otherwise, +      unless required by applicable law (such as deliberate and grossly +      negligent acts) or agreed to in writing, shall any Contributor be +      liable to You for damages, including any direct, indirect, special, +      incidental, or consequential damages of any character arising as a +      result of this License or out of the use or inability to use the +      Work (including but not limited to damages for loss of goodwill, +      work stoppage, computer failure or malfunction, or any and all +      other commercial damages or losses), even if such Contributor +      has been advised of the possibility of such damages. + +   9. Accepting Warranty or Additional Liability. While redistributing +      the Work or Derivative Works thereof, You may choose to offer, +      and charge a fee for, acceptance of support, warranty, indemnity, +      or other liability obligations and/or rights consistent with this +      License. However, in accepting such obligations, You may act only +      on Your own behalf and on Your sole responsibility, not on behalf +      of any other Contributor, and only if You agree to indemnify, +      defend, and hold each Contributor harmless for any liability +      incurred by, or claims asserted against, such Contributor by reason +      of your accepting any such warranty or additional liability. + +   END OF TERMS AND CONDITIONS diff --git a/puppet/modules/openvpn/Modulefile b/puppet/modules/openvpn/Modulefile new file mode 100644 index 00000000..679e7e64 --- /dev/null +++ b/puppet/modules/openvpn/Modulefile @@ -0,0 +1,11 @@ +name    'luxflux-openvpn' +version '2.1.0' +source 'https://github.com/luxflux/puppet-openvpn' +author 'luxflux' +license 'Apache 2.0' +summary 'OpenVPN server puppet module' +description 'Puppet module to manage OpenVPN servers' +project_page 'https://github.com/luxflux/puppet-openvpn' + +## Add dependencies, if any: +dependency 'ripienaar/concat', '0.2.0' diff --git a/puppet/modules/openvpn/Rakefile b/puppet/modules/openvpn/Rakefile new file mode 100644 index 00000000..14f1c246 --- /dev/null +++ b/puppet/modules/openvpn/Rakefile @@ -0,0 +1,2 @@ +require 'rubygems' +require 'puppetlabs_spec_helper/rake_tasks' diff --git a/puppet/modules/openvpn/Readme.markdown b/puppet/modules/openvpn/Readme.markdown new file mode 100644 index 00000000..6bcf49ea --- /dev/null +++ b/puppet/modules/openvpn/Readme.markdown @@ -0,0 +1,54 @@ +# OpenVPN Puppet module + +Puppet module to manage OpenVPN servers + +## Features: + +* Client-specific rules and access policies +* Generated client configurations and SSL-Certificates +* Downloadable client configurations and SSL-Certificates for easy client configuration +* Support for multiple server instances + +Tested on Ubuntu Precise Pangolin, CentOS 6, RedHat 6. + + +## Dependencies +  - [puppet-concat](https://github.com/ripienaar/puppet-concat) + + +## Example + +```puppet +  # add a server instance +  openvpn::server { 'winterthur': +    country      => 'CH', +    province     => 'ZH', +    city         => 'Winterthur', +    organization => 'example.org', +    email        => 'root@example.org', +    server       => '10.200.200.0 255.255.255.0' +  } + +  # define clients +  openvpn::client { 'client1': +    server => 'winterthur' +  } +  openvpn::client { 'client2': +    server   => 'winterthur' +  } + +  openvpn::client_specific_config { 'client1': +    server => 'winterthur', +    ifconfig => '10.200.200.50 255.255.255.0' +  } +``` + +Don't forget the [sysctl](https://github.com/luxflux/puppet-sysctl) directive ```net.ipv4.ip_forward```! + + +# Contributors + +These fine folks helped to get this far with this module: +* [@jlambert121](https://github.com/jlambert121) +* [@jlk](https://github.com/jlk) +* [@elisiano](https://github.com/elisiano) diff --git a/puppet/modules/openvpn/Vagrantfile b/puppet/modules/openvpn/Vagrantfile new file mode 100644 index 00000000..88875ff8 --- /dev/null +++ b/puppet/modules/openvpn/Vagrantfile @@ -0,0 +1,42 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +def server_config(config) +  config.vm.provision :puppet, :module_path => '..' do |puppet| +    puppet.manifests_path = "vagrant" +    puppet.manifest_file  = "server.pp" +  end +end + +def client_config(config) +  config.vm.provision :puppet, :module_path => '..' do |puppet| +    puppet.manifests_path = "vagrant" +    puppet.manifest_file  = "client.pp" +  end +end + +Vagrant::Config.run do |config| + +  config.vm.define :server_ubuntu do |c| +    c.vm.box = 'precise64' +    server_config c +    c.vm.network :hostonly, '10.255.255.10' +  end + +  config.vm.define :server_centos do |c| +    c.vm.box = 'centos63' + +    c.vm.provision :shell, :inline => 'if [ ! -f rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm ]; then wget -q http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm; fi' +    c.vm.provision :shell, :inline => 'yum install -y rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm || exit 0' + +    server_config c +    c.vm.network :hostonly, '10.255.255.11' +  end + +  config.vm.define :client_ubuntu do |c| +    c.vm.box = 'precise64' +    client_config c +    c.vm.network :hostonly, '10.255.255.20' +  end + +end diff --git a/puppet/modules/openvpn/manifests/client.pp b/puppet/modules/openvpn/manifests/client.pp new file mode 100644 index 00000000..92c6aa4e --- /dev/null +++ b/puppet/modules/openvpn/manifests/client.pp @@ -0,0 +1,187 @@ +# == Define: openvpn::client +# +# This define creates the client certs for a specified openvpn server as well +# as creating a tarball that can be directly imported into openvpn clients +# +# +# === Parameters +# +# [*server*] +#   String.  Name of the corresponding openvpn endpoint +#   Required +# +# [*compression*] +#   String.  Which compression algorithim to use +#   Default: comp-lzo +#   Options: comp-lzo or '' (disable compression) +# +# [*dev*] +#   String.  Device method +#   Default: tun +#   Options: tun (routed connections), tap (bridged connections) +# +# [*mute*] +#   Integer.  Set log mute level +#   Default: 20 +# +# [*mute_replay_warnings*] +#   Boolean.  Silence duplicate packet warnings (common on wireless networks) +#   Default: true +# +# [*nobind*] +#   Boolean.  Whether or not to bind to a specific port number +#   Default: true +# +# [*persist_key*] +#   Boolean.  Try to retain access to resources that may be unavailable +#     because of privilege downgrades +#   Default: true +# +# [*persist_tun*] +#   Boolean.  Try to retain access to resources that may be unavailable +#     because of privilege downgrades +#   Default: true +# +# [*port*] +#   Integer.  The port the openvpn server service is running on +#   Default: 1194 +# +# [*proto*] +#   String.  What IP protocol is being used. +#   Default: tcp +#   Options: tcp or udp +# +# [*remote_host*] +#   String.  The IP or hostname of the openvpn server service +#   Default: FQDN +# +# [*resolv_retry*] +#   Integer/String. How many seconds should the openvpn client try to resolve +#     the server's hostname +#   Default: infinite +#   Options: Integer or infinite +# +# [*verb*] +#   Integer.  Level of logging verbosity +#   Default: 3 +# +# +# === Examples +# +#   openvpn::client { +#     'my_user': +#       server      => 'contractors', +#       remote_host => 'vpn.mycompany.com' +#    } +# +# * Removal: +#     Manual process right now, todo for the future +# +# +# === Authors +# +# * Raffael Schmid <mailto:raffael@yux.ch> +# * John Kinsella <mailto:jlkinsel@gmail.com> +# * Justin Lambert <mailto:jlambert@letsevenup.com> +# +# === License +# +# Copyright 2013 Raffael Schmid, <raffael@yux.ch> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +define openvpn::client( +  $server, +  $compression = 'comp-lzo', +  $dev = 'tun', +  $mute = '20', +  $mute_replay_warnings = true, +  $nobind = true, +  $persist_key = true, +  $persist_tun = true, +  $port = '1194', +  $proto = 'tcp', +  $remote_host = $::fqdn, +  $resolv_retry = 'infinite', +  $verb = '3', +) { + +  Openvpn::Server[$server] -> +  Openvpn::Client[$name] + +  exec { +    "generate certificate for ${name} in context of ${server}": +      command  => ". ./vars && ./pkitool ${name}", +      cwd      => "/etc/openvpn/${server}/easy-rsa", +      creates  => "/etc/openvpn/${server}/easy-rsa/keys/${name}.crt", +      provider => 'shell'; +  } + +  file { +    [ "/etc/openvpn/${server}/download-configs/${name}", +      "/etc/openvpn/${server}/download-configs/${name}/keys"]: +        ensure  => directory; + +    "/etc/openvpn/${server}/download-configs/${name}/keys/${name}.crt": +      ensure  => link, +      target  => "/etc/openvpn/${server}/easy-rsa/keys/${name}.crt", +      require => Exec["generate certificate for ${name} in context of ${server}"]; + +    "/etc/openvpn/${server}/download-configs/${name}/keys/${name}.key": +      ensure  => link, +      target  => "/etc/openvpn/${server}/easy-rsa/keys/${name}.key", +      require => Exec["generate certificate for ${name} in context of ${server}"]; + +    "/etc/openvpn/${server}/download-configs/${name}/keys/ca.crt": +      ensure  => link, +      target  => "/etc/openvpn/${server}/easy-rsa/keys/ca.crt", +      require => Exec["generate certificate for ${name} in context of ${server}"]; + +    "/etc/openvpn/${server}/download-configs/${name}/${name}.conf": +      owner   => root, +      group   => root, +      mode    => '0444', +      content => template('openvpn/client.erb'), +      notify  => Exec["tar the thing ${server} with ${name}"]; +  } + +  exec { +    "tar the thing ${server} with ${name}": +      cwd         => "/etc/openvpn/${server}/download-configs/", +      command     => "/bin/rm ${name}.tar.gz; tar --exclude=\\*.conf.d -chzvf ${name}.tar.gz ${name}", +      refreshonly => true, +      require     => [  File["/etc/openvpn/${server}/download-configs/${name}/${name}.conf"], +                        File["/etc/openvpn/${server}/download-configs/${name}/keys/ca.crt"], +                        File["/etc/openvpn/${server}/download-configs/${name}/keys/${name}.key"], +                        File["/etc/openvpn/${server}/download-configs/${name}/keys/${name}.crt"] +                      ], +      notify      => Exec["generate ${name}.ovpn in ${server}"]; +  } + +  exec { +    "generate ${name}.ovpn in ${server}": +      cwd         => "/etc/openvpn/${server}/download-configs/", +      command     => "/bin/rm ${name}.ovpn; cat  ${name}/${name}.conf|perl -lne 'if(m|^ca keys/ca.crt|){ chomp(\$ca=`cat ${name}/keys/ca.crt`); print \"<ca>\n\$ca\n</ca>\"} elsif(m|^cert keys/${name}.crt|) { chomp(\$crt=`cat ${name}/keys/${name}.crt`); print \"<cert>\n\$crt\n</cert>\"} elsif(m|^key keys/${name}.key|){ chomp(\$key=`cat ${name}/keys/${name}.key`); print \"<key>\n\$key\n</key>\"} else { print} ' > ${name}.ovpn", +      refreshonly => true, +      require     => [  File["/etc/openvpn/${server}/download-configs/${name}/${name}.conf"], +                        File["/etc/openvpn/${server}/download-configs/${name}/keys/ca.crt"], +                        File["/etc/openvpn/${server}/download-configs/${name}/keys/${name}.key"], +                        File["/etc/openvpn/${server}/download-configs/${name}/keys/${name}.crt"], +                      ], +  } + +  file { "/etc/openvpn/${server}/download-configs/${name}.ovpn": +    mode    => '0400', +    require => Exec["generate ${name}.ovpn in ${server}"], +  } +} diff --git a/puppet/modules/openvpn/manifests/client_specific_config.pp b/puppet/modules/openvpn/manifests/client_specific_config.pp new file mode 100644 index 00000000..4287421a --- /dev/null +++ b/puppet/modules/openvpn/manifests/client_specific_config.pp @@ -0,0 +1,79 @@ +# == Define: openvpn::client_specific_config +# +# This define configures options which will be pushed by the server to a +# specific client only. This feature is explained here: +#  http://openvpn.net/index.php/open-source/documentation/howto.html#policy +# +# === Parameters +# +# All the parameters are explained in the openvpn documentation: +#   http://openvpn.net/index.php/open-source/documentation/howto.html#policy +# +# [*server*] +#   String.  Name of the corresponding openvpn endpoint +#   Required +# +# [*iroute*] +#   Array.  Array of iroute combinations. +#   Default: [] +# +# [*ifconfig*] +#   String.  IP configuration to push to the client. +#   Default: false +# +# [*dhcp_options] +#   Array.  DHCP options to push to the client. +#   Default: [] +# +# +# === Examples +# +#   openvpn::client_specific_config { +#     'vpn_client': +#       server       => 'contractors', +#       iroute       => ['10.0.1.0 255.255.255.0'], +#       ifconfig     => '10.10.10.1 10.10.10.2', +#       dhcp_options => ['DNS 8.8.8.8'] +#    } +# +# * Removal: +#     Manual process right now, todo for the future +# +# +# === Authors +# +# * Raffael Schmid <mailto:raffael@yux.ch> +# +# === License +# +# Copyright 2013 Raffael Schmid, <raffael@yux.ch> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +define openvpn::client_specific_config( +  $server, +  $iroute       = [], +  $ifconfig     = false, +  $dhcp_options = [] +) { + +  Openvpn::Server[$server] -> +  Openvpn::Client[$name] -> +  Openvpn::Client_specific_config[$name] + +  file { "/etc/openvpn/${server}/client-configs/${name}": +    ensure  => present, +    content => template('openvpn/client_specific_config.erb') +  } + +} diff --git a/puppet/modules/openvpn/manifests/config.pp b/puppet/modules/openvpn/manifests/config.pp new file mode 100644 index 00000000..32b32094 --- /dev/null +++ b/puppet/modules/openvpn/manifests/config.pp @@ -0,0 +1,52 @@ +# == Class: openvpn::config +# +# This class sets up the openvpn enviornment as well as the default config file +# +# +# === Examples +# +# This class should not be directly invoked +# +# === Authors +# +# * Raffael Schmid <mailto:raffael@yux.ch> +# * John Kinsella <mailto:jlkinsel@gmail.com> +# * Justin Lambert <mailto:jlambert@letsevenup.com> +# +# === License +# +# Copyright 2013 Raffael Schmid, <raffael@yux.ch> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class openvpn::config { + +  if $::osfamily == 'Debian' { +    include concat::setup + +    concat { +      '/etc/default/openvpn': +        owner  => root, +        group  => root, +        mode   => 644, +        warn   => true; +    } + +    concat::fragment { +      'openvpn.default.header': +        content => template('openvpn/etc-default-openvpn.erb'), +        target  => '/etc/default/openvpn', +        order   => 01; +    } +  } +} diff --git a/puppet/modules/openvpn/manifests/init.pp b/puppet/modules/openvpn/manifests/init.pp new file mode 100644 index 00000000..7e07f025 --- /dev/null +++ b/puppet/modules/openvpn/manifests/init.pp @@ -0,0 +1,43 @@ +# == Class: openvpn +# +# This module installs the openvpn service, configures vpn endpoints, generates +# client certificates, and generates client config files +# +# +# === Examples +# +# * Installation: +#     class { 'openvpn': } +# +# +# === Authors +# +# * Raffael Schmid <mailto:raffael@yux.ch> +# * John Kinsella <mailto:jlkinsel@gmail.com> +# * Justin Lambert <mailto:jlambert@letsevenup.com> +# +# === License +# +# Copyright 2013 Raffael Schmid, <raffael@yux.ch> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class openvpn { + +  class {'openvpn::params': } -> +  class {'openvpn::install': } -> +  class {'openvpn::config': } ~> +  class {'openvpn::service': } -> +  Class['openvpn'] + +} diff --git a/puppet/modules/openvpn/manifests/install.pp b/puppet/modules/openvpn/manifests/install.pp new file mode 100644 index 00000000..a230373a --- /dev/null +++ b/puppet/modules/openvpn/manifests/install.pp @@ -0,0 +1,46 @@ +# == Class: openvpn +# +# This module installs the openvpn service, configures vpn endpoints, generates +# client certificates, and generates client config files +# +# +# === Examples +# +# This class should not be directly invoked +# +# +# === Authors +# +# * Raffael Schmid <mailto:raffael@yux.ch> +# * John Kinsella <mailto:jlkinsel@gmail.com> +# * Justin Lambert <mailto:jlambert@letsevenup.com> +# +# === License +# +# Copyright 2013 Raffael Schmid, <raffael@yux.ch> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class openvpn::install { + +  package { +    'openvpn': +      ensure => installed; +  } + +  file { +    [ '/etc/openvpn', '/etc/openvpn/keys' ]: +      ensure  => directory, +      require => Package['openvpn']; +  } +} diff --git a/puppet/modules/openvpn/manifests/params.pp b/puppet/modules/openvpn/manifests/params.pp new file mode 100644 index 00000000..33495270 --- /dev/null +++ b/puppet/modules/openvpn/manifests/params.pp @@ -0,0 +1,37 @@ +# === License +# +# Copyright 2013 Raffael Schmid, <raffael@yux.ch> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class openvpn::params { + +  $group = $::osfamily ? { +    'RedHat' => 'nobody', +    default  => 'nogroup' +  } + +  $easyrsa_source = $::osfamily ? { +    'RedHat'  => $::operatingsystemmajrelease ? { +      6 => '/usr/share/openvpn/easy-rsa/2.0', +      default => '/usr/share/doc/openvpn-2.2.2/easy-rsa/2.0' +    }, +    default   => '/usr/share/doc/openvpn/examples/easy-rsa/2.0' +  } + +  $link_openssl_cnf = $::osfamily ? { +    /(Debian|RedHat)/ => true, +    default           => false +  } + +} diff --git a/puppet/modules/openvpn/manifests/server.pp b/puppet/modules/openvpn/manifests/server.pp new file mode 100644 index 00000000..649048c4 --- /dev/null +++ b/puppet/modules/openvpn/manifests/server.pp @@ -0,0 +1,233 @@ +# == Define: openvpn::server +# +# This define creates the openvpn server instance and ssl certificates +# +# +# === Parameters +# +# [*country*] +#   String.  Country to be used for the SSL certificate +# +# [*province*] +#   String.  Province to be used for the SSL certificate +# +# [*city*] +#   String.  City to be used for the SSL certificate +# +# [*organization*] +#   String.  Organization to be used for the SSL certificate +# +# [*email*] +#   String.  Email address to be used for the SSL certificate +# +# [*compression*] +#   String.  Which compression algorithim to use +#   Default: comp-lzo +#   Options: comp-lzo or '' (disable compression) +# +# [*dev*] +#   String.  Device method +#   Default: tun +#   Options: tun (routed connections), tap (bridged connections) +# +# [*user*] +#   String.  Group to drop privileges to after startup +#   Default: nobody +# +# [*group*] +#   String.  User to drop privileges to after startup +#   Default: depends on your $::osfamily +# +# [*ipp*] +#   Boolean.  Persist ifconfig information to a file to retain client IP +#     addresses between sessions +#   Default: false +# +# [*local*] +#   String.  Interface for openvpn to bind to. +#   Default: $::ipaddress_eth0 +#   Options: An IP address or '' to bind to all ip addresses +# +# [*logfile*] +#   String.  Logfile for this openvpn server +#   Default: false +#   Options: false (syslog) or log file name +# +# [*port*] +#   Integer.  The port the openvpn server service is running on +#   Default: 1194 +# +# [*proto*] +#   String.  What IP protocol is being used. +#   Default: tcp +#   Options: tcp or udp +# +# [*status_log*] +#   String.  Logfile for periodic dumps of the vpn service status +#   Default: "${name}/openvpn-status.log" +# +# [*server*] +#   String.  Network to assign client addresses out of +#   Default: None.  Required in tun mode, not in tap mode +# +# [*push*] +#   Array.  Options to push out to the client.  This can include routes, DNS +#     servers, DNS search domains, and many other options. +#   Default: [] +# +# +# === Examples +# +#   openvpn::client { +#     'my_user': +#       server      => 'contractors', +#       remote_host => 'vpn.mycompany.com' +#    } +# +# * Removal: +#     Manual process right now, todo for the future +# +# +# === Authors +# +# * Raffael Schmid <mailto:raffael@yux.ch> +# * John Kinsella <mailto:jlkinsel@gmail.com> +# * Justin Lambert <mailto:jlambert@letsevenup.com> +# +# === License +# +# Copyright 2013 Raffael Schmid, <raffael@yux.ch> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +define openvpn::server( +  $country, +  $province, +  $city, +  $organization, +  $email, +  $compression = 'comp-lzo', +  $dev = 'tun0', +  $user = 'nobody', +  $group = false, +  $ipp = false, +  $ip_pool = [], +  $local = $::ipaddress_eth0, +  $logfile = false, +  $port = '1194', +  $proto = 'tcp', +  $status_log = "${name}/openvpn-status.log", +  $server = '', +  $push = [] +) { + +  include openvpn +  Class['openvpn::install'] -> +  Openvpn::Server[$name] ~> +  Class['openvpn::service'] + +  $tls_server = $proto ? { +    /tcp/   => true, +    default => false +  } + +  $group_to_set = $group ? { +    false   => $openvpn::params::group, +    default => $group +  } + +  file { +    ["/etc/openvpn/${name}", "/etc/openvpn/${name}/client-configs", "/etc/openvpn/${name}/download-configs" ]: +      ensure  => directory; +  } + +  exec { +    "copy easy-rsa to openvpn config folder ${name}": +      command => "/bin/cp -r ${openvpn::params::easyrsa_source} /etc/openvpn/${name}/easy-rsa", +      creates => "/etc/openvpn/${name}/easy-rsa", +      notify  => Exec["fix_easyrsa_file_permissions_${name}"], +      require => File["/etc/openvpn/${name}"]; +  } + +  exec { +    "fix_easyrsa_file_permissions_${name}": +      refreshonly => true, +      command     => "/bin/chmod 755 /etc/openvpn/${name}/easy-rsa/*"; +  } + +  file { +    "/etc/openvpn/${name}/easy-rsa/vars": +      ensure  => present, +      content => template('openvpn/vars.erb'), +      require => Exec["copy easy-rsa to openvpn config folder ${name}"]; +  } + +  file { +    "/etc/openvpn/${name}/easy-rsa/openssl.cnf": +      require => Exec["copy easy-rsa to openvpn config folder ${name}"]; +  } + +  if $openvpn::params::link_openssl_cnf == true { +    File["/etc/openvpn/${name}/easy-rsa/openssl.cnf"] { +      ensure => link, +      target => "/etc/openvpn/${name}/easy-rsa/openssl-1.0.0.cnf" +    } +  } + +  exec { +    "generate dh param ${name}": +      command  => '. ./vars && ./clean-all && ./build-dh', +      cwd      => "/etc/openvpn/${name}/easy-rsa", +      creates  => "/etc/openvpn/${name}/easy-rsa/keys/dh1024.pem", +      provider => 'shell', +      require  => File["/etc/openvpn/${name}/easy-rsa/vars"]; + +    "initca ${name}": +      command  => '. ./vars && ./pkitool --initca', +      cwd      => "/etc/openvpn/${name}/easy-rsa", +      creates  => "/etc/openvpn/${name}/easy-rsa/keys/ca.key", +      provider => 'shell', +      require  => [ Exec["generate dh param ${name}"], File["/etc/openvpn/${name}/easy-rsa/openssl.cnf"] ]; + +    "generate server cert ${name}": +      command  => '. ./vars && ./pkitool --server server', +      cwd      => "/etc/openvpn/${name}/easy-rsa", +      creates  => "/etc/openvpn/${name}/easy-rsa/keys/server.key", +      provider => 'shell', +      require  => Exec["initca ${name}"]; +  } + +  file { +    "/etc/openvpn/${name}/keys": +      ensure  => link, +      target  => "/etc/openvpn/${name}/easy-rsa/keys", +      require => Exec["copy easy-rsa to openvpn config folder ${name}"]; +  } + +  if $::osfamily == 'Debian' { +    concat::fragment { +      "openvpn.default.autostart.${name}": +        content => "AUTOSTART=\"\$AUTOSTART ${name}\"\n", +        target  => '/etc/default/openvpn', +        order   => 10; +    } +  } + +  file { +    "/etc/openvpn/${name}.conf": +      owner   => root, +      group   => root, +      mode    => '0444', +      content => template('openvpn/server.erb'); +  } +} diff --git a/puppet/modules/openvpn/manifests/service.pp b/puppet/modules/openvpn/manifests/service.pp new file mode 100644 index 00000000..54e8db7d --- /dev/null +++ b/puppet/modules/openvpn/manifests/service.pp @@ -0,0 +1,36 @@ +# == Class: openvpn::config +# +# This class maintains the openvpn service +# +# +# === Examples +# +# This class should not be directly invoked +# +# === Authors +# +# * Raffael Schmid <mailto:raffael@yux.ch> +# * John Kinsella <mailto:jlkinsel@gmail.com> +# * Justin Lambert <mailto:jlambert@letsevenup.com> +# +# === License +# +# Copyright 2013 Raffael Schmid, <raffael@yux.ch> +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# lied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class openvpn::service { +  service { +    'openvpn': +      ensure     => running, +      enable     => true, +      hasrestart => true, +      hasstatus  => true; +  } +} diff --git a/puppet/modules/openvpn/spec/classes/openvpn_config_spec.rb b/puppet/modules/openvpn/spec/classes/openvpn_config_spec.rb new file mode 100644 index 00000000..bbb63a77 --- /dev/null +++ b/puppet/modules/openvpn/spec/classes/openvpn_config_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' +  +describe 'openvpn::config', :type => :class do +   +  it { should create_class('openvpn::config') } +   +  context "on Debian based machines" do +    let (:facts) { { :osfamily => 'Debian', :concat_basedir => '/var/lib/puppet/concat' } } + +    it { should contain_class('concat::setup') } +    it { should contain_concat('/etc/default/openvpn') } +    it { should contain_concat__fragment('openvpn.default.header') } +  end + +end diff --git a/puppet/modules/openvpn/spec/classes/openvpn_init_spec.rb b/puppet/modules/openvpn/spec/classes/openvpn_init_spec.rb new file mode 100644 index 00000000..45dcc9bf --- /dev/null +++ b/puppet/modules/openvpn/spec/classes/openvpn_init_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' +  +describe 'openvpn', :type => :class do + +  let (:facts) { { :concat_basedir => '/var/lib/puppet/concat' } } + +  it { should create_class('openvpn') } + +end diff --git a/puppet/modules/openvpn/spec/classes/openvpn_install_spec.rb b/puppet/modules/openvpn/spec/classes/openvpn_install_spec.rb new file mode 100644 index 00000000..cdb31358 --- /dev/null +++ b/puppet/modules/openvpn/spec/classes/openvpn_install_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' +  +describe 'openvpn::install', :type => :class do + +  it { should create_class('openvpn::install') } +  it { should contain_package('openvpn') } + +  it { should contain_file('/etc/openvpn').with('ensure' => 'directory') } +  it { should contain_file('/etc/openvpn/keys').with('ensure' => 'directory') } + +end diff --git a/puppet/modules/openvpn/spec/classes/openvpn_service_spec.rb b/puppet/modules/openvpn/spec/classes/openvpn_service_spec.rb new file mode 100644 index 00000000..f427e7f1 --- /dev/null +++ b/puppet/modules/openvpn/spec/classes/openvpn_service_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' +  +describe 'openvpn::service', :type => :class do + +  let (:facts) { { :concat_basedir => '/var/lib/puppet/concat' } } + +  it { should create_class('openvpn::service') } +  it { should contain_service('openvpn').with( +    'ensure'  => 'running', +    'enable'  => true +  ) } + +end diff --git a/puppet/modules/openvpn/spec/defines/openvpn_client_spec.rb b/puppet/modules/openvpn/spec/defines/openvpn_client_spec.rb new file mode 100644 index 00000000..a4b580e8 --- /dev/null +++ b/puppet/modules/openvpn/spec/defines/openvpn_client_spec.rb @@ -0,0 +1,88 @@ +require 'spec_helper' +  +describe 'openvpn::client', :type => :define do +  let(:title) { 'test_client' } +  let(:params) { { 'server' => 'test_server' } } +  let(:facts) { { :fqdn => 'somehost', :concat_basedir => '/var/lib/puppet/concat' } } +  let(:pre_condition) do +    'openvpn::server { "test_server": +      country       => "CO", +      province      => "ST", +      city          => "Some City", +      organization  => "example.org", +      email         => "testemail@example.org" +    }' +  end + +  it { should contain_exec('generate certificate for test_client in context of test_server') } + +  [ 'test_client', 'test_client/keys'].each do |directory| +    it { should contain_file("/etc/openvpn/test_server/download-configs/#{directory}") } +  end + +  [ 'test_client.crt', 'test_client.key', 'ca.crt' ].each do |file| +    it { should contain_file("/etc/openvpn/test_server/download-configs/test_client/keys/#{file}").with( +      'ensure'  => 'link', +      'target'  => "/etc/openvpn/test_server/easy-rsa/keys/#{file}" +    )} +  end +   +  it { should contain_exec('tar the thing test_server with test_client').with( +    'cwd'     => '/etc/openvpn/test_server/download-configs/', +    'command' => '/bin/rm test_client.tar.gz; tar --exclude=\*.conf.d -chzvf test_client.tar.gz test_client' +  ) } + +  context "setting the minimum parameters" do +    let(:params) { { 'server' => 'test_server' } } +    let(:facts) { { :fqdn => 'somehost', :concat_basedir => '/var/lib/puppet/concat' } } + +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^client$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^ca\s+keys\/ca\.crt$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^cert\s+keys\/test_client.crt$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^key\s+keys\/test_client\.key$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^dev\s+tun$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^proto\s+tcp$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^remote\s+somehost\s+1194$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^comp-lzo$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^resolv-retry\s+infinite$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^nobind$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^persist-key$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^persist-tun$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^mute-replay-warnings$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^ns\-cert\-type\s+server$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^verb\s+3$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^mute\s+20$/)} +  end + +  context "setting all of the parameters" do +    let(:params) { {  +      'server'                => 'test_server', +      'compression'           => 'comp-something', +      'dev'                   => 'tap', +      'mute'                  => 10, +      'mute_replay_warnings'  => false, +      'nobind'                => false, +      'persist_key'           => false, +      'persist_tun'           => false, +      'port'                  => '123', +      'proto'                 => 'udp', +      'remote_host'           => 'somewhere', +      'resolv_retry'          => '2m', +      'verb'                  => '1' +    } } +    let(:facts) { { :fqdn => 'somehost', :concat_basedir => '/var/lib/puppet/concat' } } + +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^client$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^ca\s+keys\/ca\.crt$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^cert\s+keys\/test_client.crt$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^key\s+keys\/test_client\.key$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^dev\s+tap$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^proto\s+udp$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^remote\s+somewhere\s+123$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^comp-something$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^resolv-retry\s+2m$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^verb\s+1$/)} +    it { should contain_file('/etc/openvpn/test_server/download-configs/test_client/test_client.conf').with_content(/^mute\s+10$/)} +  end + +end diff --git a/puppet/modules/openvpn/spec/defines/openvpn_client_specific_config_spec.rb b/puppet/modules/openvpn/spec/defines/openvpn_client_specific_config_spec.rb new file mode 100644 index 00000000..cfdab389 --- /dev/null +++ b/puppet/modules/openvpn/spec/defines/openvpn_client_specific_config_spec.rb @@ -0,0 +1,40 @@ +require 'spec_helper' + +describe 'openvpn::client_specific_config', :type => :define do +  let(:title) { 'test_client' } +  let(:params) { { 'server' => 'test_server' } } +  let(:facts) { { :fqdn => 'somehost', :concat_basedir => '/var/lib/puppet/concat' } } +  let(:pre_condition) do +    [ +      'openvpn::server { "test_server": +        country       => "CO", +        province      => "ST", +        city          => "Some City", +        organization  => "example.org", +        email         => "testemail@example.org" +      }', +      'openvpn::client { "test_client": +        server => "test_server" +      }' +    ].join +  end + +  it { should contain_file('/etc/openvpn/test_server/client-configs/test_client') } + +  describe "setting no paramter at all" do +    it { should contain_file('/etc/openvpn/test_server/client-configs/test_client').with_content(/\A\n\z/) } +  end + +  describe "setting all parameters" do +    let(:params) do +      {:server       => 'test_server', +       :iroute       => ['10.0.1.0 255.255.255.0'], +       :ifconfig     => '10.10.10.2 255.255.255.0', +       :dhcp_options => ['DNS 8.8.8.8']} +    end + +    it { should contain_file('/etc/openvpn/test_server/client-configs/test_client').with_content(/^iroute 10.0.1.0 255.255.255.0$/) } +    it { should contain_file('/etc/openvpn/test_server/client-configs/test_client').with_content(/^ifconfig-push 10.10.10.2 255.255.255.0$/) } +    it { should contain_file('/etc/openvpn/test_server/client-configs/test_client').with_content(/^push dhcp-option DNS 8.8.8.8$/) } +  end +end diff --git a/puppet/modules/openvpn/spec/defines/openvpn_server_spec.rb b/puppet/modules/openvpn/spec/defines/openvpn_server_spec.rb new file mode 100644 index 00000000..467be6aa --- /dev/null +++ b/puppet/modules/openvpn/spec/defines/openvpn_server_spec.rb @@ -0,0 +1,165 @@ +require 'spec_helper' + +describe 'openvpn::server', :type => :define do + +  let(:title) { 'test_server' } + +  context "creating a server with the minimum parameters" do +    let(:params) { { +      'country'       => 'CO', +      'province'      => 'ST', +      'city'          => 'Some City', +      'organization'  => 'example.org', +      'email'         => 'testemail@example.org' +    } } + +    let (:facts) { { +      :ipaddress_eth0 => '1.2.3.4', +      :network_eth0   => '1.2.3.0', +      :netmask_eth0   => '255.255.255.0', +      :concat_basedir => '/var/lib/puppet/concat', +      :osfamily       => 'anything_else' +    } } + +    # Files associated with a server config +    it { should contain_file('/etc/openvpn/test_server').with('ensure' => 'directory')} +    it { should contain_file('/etc/openvpn/test_server/client-configs').with('ensure' => 'directory')} +    it { should contain_file('/etc/openvpn/test_server/download-configs').with('ensure' => 'directory')} +    it { should contain_file('/etc/openvpn/test_server/easy-rsa/vars')} +    it { should contain_file('/etc/openvpn/test_server/easy-rsa/openssl.cnf')} +    it { should contain_file('/etc/openvpn/test_server/keys').with( +      'ensure'  => 'link', +      'target'  => '/etc/openvpn/test_server/easy-rsa/keys' +    )} + +    # Execs to working with certificates +    it { should contain_exec('copy easy-rsa to openvpn config folder test_server').with( +      'command' => '/bin/cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/openvpn/test_server/easy-rsa' +    )} +    it { should contain_exec('generate dh param test_server') } +    it { should contain_exec('initca test_server') } +    it { should contain_exec('generate server cert test_server') } + +    # VPN server config file itself +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^mode\s+server$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^client\-config\-dir\s+\/etc\/openvpn\/test_server\/client\-configs$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^ca\s+\/etc\/openvpn\/test_server\/keys\/ca.crt$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^cert\s+\/etc\/openvpn\/test_server\/keys\/server.crt$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^key\s+\/etc\/openvpn\/test_server\/keys\/server.key$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^dh\s+\/etc\/openvpn\/test_server\/keys\/dh1024.pem$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^proto\s+tcp-server$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^tls-server$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^port\s+1194$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^comp-lzo$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^group\s+nogroup$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^user\s+nobody$/) } +    it { should_not contain_file('/etc/openvpn/test_server.conf').with_content(/^log\-append\s+test_server\/openvpn\.log$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^status\s+test_server\/openvpn\-status\.log$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^dev\s+tun0$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^local\s+1\.2\.3\.4$/) } +    it { should_not contain_file('/etc/openvpn/test_server.conf').with_content(/^ifconfig-pool-persist/) } +  end + +  context "creating a server setting all parameters" do +    let(:params) { { +      'country'       => 'CO', +      'province'      => 'ST', +      'city'          => 'Some City', +      'organization'  => 'example.org', +      'email'         => 'testemail@example.org', +      'compression'   => 'fake_compression', +      'port'          => '123', +      'proto'         => 'udp', +      'group'         => 'someone', +      'user'          => 'someone', +      'logfile'       => '/var/log/openvpn/test_server.log', +      'status_log'    => '/var/log/openvpn/test_server_status.log', +      'dev'           => 'tun1', +      'local'         => '2.3.4.5', +      'ipp'           => true, +      'server'        => '2.3.4.0 255.255.0.0', +      'push'          => [ 'dhcp-option DNS 172.31.0.30', 'route 172.31.0.0 255.255.0.0' ] +    } } + +    let (:facts) { { +      :ipaddress_eth0 => '1.2.3.4', +      :network_eth0   => '1.2.3.0', +      :netmask_eth0   => '255.255.255.0', +      :concat_basedir => '/var/lib/puppet/concat' +    } } + +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^mode\s+server$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^client\-config\-dir\s+\/etc\/openvpn\/test_server\/client\-configs$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^ca\s+\/etc\/openvpn\/test_server\/keys\/ca.crt$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^cert\s+\/etc\/openvpn\/test_server\/keys\/server.crt$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^key\s+\/etc\/openvpn\/test_server\/keys\/server.key$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^dh\s+\/etc\/openvpn\/test_server\/keys\/dh1024.pem$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^proto\s+udp$/) } +    it { should_not contain_file('/etc/openvpn/test_server.conf').with_content(/^proto\s+tls-server$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^port\s+123$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^fake_compression$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^group\s+someone$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^user\s+someone$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^log\-append\s+\/var\/log\/openvpn\/test_server\.log$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^status\s+\/var\/log\/openvpn\/test_server_status\.log$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^dev\s+tun1$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^local\s+2\.3\.4\.5$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^server\s+2\.3\.4\.0\s+255\.255\.0\.0$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^push\s+dhcp-option\s+DNS\s+172\.31\.0\.30$/) } +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^push\s+route\s+172\.31\.0\.0\s+255\.255\.0\.0$/) } +  end + +  context "when RedHat based machine" do +    let(:params) { { +      'country'       => 'CO', +      'province'      => 'ST', +      'city'          => 'Some City', +      'organization'  => 'example.org', +      'email'         => 'testemail@example.org' +    } } + +    let(:facts) { { :osfamily => 'RedHat', :concat_basedir => '/var/lib/puppet/concat' } } + +    it { should contain_file('/etc/openvpn/test_server/easy-rsa/openssl.cnf').with( +      'ensure'  => 'link', +      'target'  => '/etc/openvpn/test_server/easy-rsa/openssl-1.0.0.cnf' +    )} + +    it { should contain_exec('copy easy-rsa to openvpn config folder test_server').with( +      'command' => '/bin/cp -r /usr/share/doc/openvpn-2.2.2/easy-rsa/2.0 /etc/openvpn/test_server/easy-rsa' +    )} +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^group\s+nobody$/) } + +  end + +  context "when Debian based machine" do +    let(:params) { { +      'country'       => 'CO', +      'province'      => 'ST', +      'city'          => 'Some City', +      'organization'  => 'example.org', +      'email'         => 'testemail@example.org' +    } } + +    let(:facts) { { :osfamily => 'Debian', :concat_basedir => '/var/lib/puppet/concat' } } + +    it { should contain_file('/etc/openvpn/test_server/easy-rsa/openssl.cnf').with( +      'ensure'  => 'link', +      'target'  => '/etc/openvpn/test_server/easy-rsa/openssl-1.0.0.cnf' +    )} + +    it { should contain_exec('copy easy-rsa to openvpn config folder test_server').with( +      'command' => '/bin/cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/openvpn/test_server/easy-rsa' +    )} + +    # Configure to start vpn session +    it { should contain_concat__fragment('openvpn.default.autostart.test_server').with( +      'content' => "AUTOSTART=\"$AUTOSTART test_server\"\n", +      'target'  => '/etc/default/openvpn' +    )} + +    it { should contain_file('/etc/openvpn/test_server.conf').with_content(/^group\s+nogroup$/) } + +  end + +end diff --git a/puppet/modules/openvpn/spec/spec_helper.rb b/puppet/modules/openvpn/spec/spec_helper.rb new file mode 100644 index 00000000..dc7e9f4a --- /dev/null +++ b/puppet/modules/openvpn/spec/spec_helper.rb @@ -0,0 +1,2 @@ +require 'rubygems' +require 'puppetlabs_spec_helper/module_spec_helper' diff --git a/puppet/modules/openvpn/templates/client.erb b/puppet/modules/openvpn/templates/client.erb new file mode 100644 index 00000000..021ed617 --- /dev/null +++ b/puppet/modules/openvpn/templates/client.erb @@ -0,0 +1,26 @@ +client +ca keys/ca.crt +cert keys/<%= scope.lookupvar('name') %>.crt +key keys/<%= scope.lookupvar('name') %>.key +dev <%= scope.lookupvar('dev') %> +proto <%= scope.lookupvar('proto') %> +remote <%= scope.lookupvar('remote_host') %> <%= scope.lookupvar('port') %> +<% if scope.lookupvar('compression') != '' -%> +<%= scope.lookupvar('compression') %> +<% end -%> +resolv-retry <%= scope.lookupvar('resolv_retry') %> +<% if scope.lookupvar('nobind') -%> +nobind +<% end -%> +<% if scope.lookupvar('persist_key') -%> +persist-key +<% end -%> +<% if scope.lookupvar('persist_tun') -%> +persist-tun +<% end -%> +<% if scope.lookupvar('mute_replay_warnings') -%> +mute-replay-warnings +<% end -%> +ns-cert-type server +verb <%= scope.lookupvar('verb') %> +mute <%= scope.lookupvar('mute') %> diff --git a/puppet/modules/openvpn/templates/client_specific_config.erb b/puppet/modules/openvpn/templates/client_specific_config.erb new file mode 100644 index 00000000..62cc0e7a --- /dev/null +++ b/puppet/modules/openvpn/templates/client_specific_config.erb @@ -0,0 +1,10 @@ +<% scope.lookupvar('iroute').each do |route| -%> +iroute <%= route %> +<% end -%> +<% if ifconfig = scope.lookupvar('ifconfig') -%> +ifconfig-push <%= ifconfig %> +<% end -%> +<% scope.lookupvar('dhcp_options').each do |option| -%> +push dhcp-option <%= option %> +<% end -%> + diff --git a/puppet/modules/openvpn/templates/etc-default-openvpn.erb b/puppet/modules/openvpn/templates/etc-default-openvpn.erb new file mode 100644 index 00000000..310e462e --- /dev/null +++ b/puppet/modules/openvpn/templates/etc-default-openvpn.erb @@ -0,0 +1,20 @@ +# This is the configuration file for /etc/init.d/openvpn + +# +# Start only these VPNs automatically via init script. +# Allowed values are "all", "none" or space separated list of +# names of the VPNs. If empty, "all" is assumed. +# +#AUTOSTART="all" +#AUTOSTART="none" +#AUTOSTART="home office" +# +# Refresh interval (in seconds) of default status files +# located in /var/run/openvpn.$NAME.status +# Defaults to 10, 0 disables status file generation +# +#STATUSREFRESH=10 +#STATUSREFRESH=0 +# Optional arguments to openvpn's command line +OPTARGS="" +AUTOSTART="" diff --git a/puppet/modules/openvpn/templates/server.erb b/puppet/modules/openvpn/templates/server.erb new file mode 100644 index 00000000..6ef13263 --- /dev/null +++ b/puppet/modules/openvpn/templates/server.erb @@ -0,0 +1,37 @@ +mode server +client-config-dir /etc/openvpn/<%= scope.lookupvar('name') %>/client-configs +ca /etc/openvpn/<%= scope.lookupvar('name') %>/keys/ca.crt +cert /etc/openvpn/<%= scope.lookupvar('name') %>/keys/server.crt +key /etc/openvpn/<%= scope.lookupvar('name') %>/keys/server.key +dh /etc/openvpn/<%= scope.lookupvar('name') %>/keys/dh1024.pem +<% if scope.lookupvar('proto') == 'tcp' -%> +proto <%= scope.lookupvar('proto') %>-server +<% else -%> +proto <%= scope.lookupvar('proto') %> +<% end -%> +port <%= scope.lookupvar('port') %> +<% if scope.lookupvar('tls_server') -%> +tls-server +<% end -%> +<% if scope.lookupvar('compression') != '' -%> +<%= scope.lookupvar('compression') %> +<% end -%> +group <%= scope.lookupvar('group_to_set') %> +user <%= scope.lookupvar('user') %> +<% if scope.lookupvar('logfile') -%> +log-append <%= scope.lookupvar('logfile') %> +<% end -%> +status <%= scope.lookupvar('status_log') %> +dev <%= scope.lookupvar('dev') %> +<% if scope.lookupvar('local') != '' -%> +local <%= scope.lookupvar('local') %> +<% end -%> +<% if scope.lookupvar('ipp') -%> +ifconfig-pool-persist <%= scope.lookupvar('name') %>/vpn-ipp.txt +<% end -%> +<% if scope.lookupvar('server') != '' -%> +server <%= scope.lookupvar('server') %> +<% end -%> +<% scope.lookupvar('push').each do |item| -%> +push <%= item %> +<% end -%> diff --git a/puppet/modules/openvpn/templates/vars.erb b/puppet/modules/openvpn/templates/vars.erb new file mode 100644 index 00000000..20448b8b --- /dev/null +++ b/puppet/modules/openvpn/templates/vars.erb @@ -0,0 +1,68 @@ +# easy-rsa parameter settings + +# NOTE: If you installed from an RPM, +# don't edit this file in place in +# /usr/share/openvpn/easy-rsa -- +# instead, you should copy the whole +# easy-rsa directory to another location +# (such as /etc/openvpn) so that your +# edits will not be wiped out by a future +# OpenVPN package upgrade. + +# This variable should point to +# the top level of the easy-rsa +# tree. +export EASY_RSA="/etc/openvpn/<%= @name %>/easy-rsa" + +# +# This variable should point to +# the requested executables +# +export OPENSSL="openssl" +export PKCS11TOOL="pkcs11-tool" +export GREP="grep" + + +# This variable should point to +# the openssl.cnf file included +# with easy-rsa. +export KEY_CONFIG=`$EASY_RSA/whichopensslcnf $EASY_RSA` + +# Edit this variable to point to +# your soon-to-be-created key +# directory. +# +# WARNING: clean-all will do +# a rm -rf on this directory +# so make sure you define +# it correctly! +export KEY_DIR="$EASY_RSA/keys" + +# Issue rm -rf warning +echo NOTE: If you run ./clean-all, I will be doing a rm -rf on $KEY_DIR + +# PKCS11 fixes +export PKCS11_MODULE_PATH="dummy" +export PKCS11_PIN="dummy" + +# Increase this to 2048 if you +# are paranoid.  This will slow +# down TLS negotiation performance +# as well as the one-time DH parms +# generation process. +export KEY_SIZE=1024 + +# In how many days should the root CA key expire? +export CA_EXPIRE=3650 + +# In how many days should certificates expire? +export KEY_EXPIRE=3650 + +# These are the default values for fields +# which will be placed in the certificate. +# Don't leave any of these fields blank. +export KEY_COUNTRY="<%= @country %>" +export KEY_PROVINCE="<%= @province %>" +export KEY_CITY="<%= @city %>" +export KEY_ORG="<%= @organization %>" +export KEY_EMAIL="<%= @email %>" diff --git a/puppet/modules/openvpn/vagrant/client.pp b/puppet/modules/openvpn/vagrant/client.pp new file mode 100644 index 00000000..7ebeb1d7 --- /dev/null +++ b/puppet/modules/openvpn/vagrant/client.pp @@ -0,0 +1,5 @@ +node default { + +  package { 'openvpn': ensure => installed; } + +} diff --git a/puppet/modules/openvpn/vagrant/server.pp b/puppet/modules/openvpn/vagrant/server.pp new file mode 100644 index 00000000..a95def06 --- /dev/null +++ b/puppet/modules/openvpn/vagrant/server.pp @@ -0,0 +1,23 @@ +node default { +  openvpn::server { 'winterthur': +    country      => 'CH', +    province     => 'ZH', +    city         => 'Winterthur', +    organization => 'example.org', +    email        => 'root@example.org', +    server       => '10.200.200.0 255.255.255.0' +  } + +  openvpn::client { 'client1': +    server => 'winterthur'; +  } + +  openvpn::client_specific_config { 'client1': +    server   => 'winterthur', +    ifconfig => '10.200.200.100 255.255.255.0' +  } + +  openvpn::client { 'client2': +    server => 'winterthur'; +  } +} diff --git a/puppet/modules/postfwd/files/postfwd_default b/puppet/modules/postfwd/files/postfwd_default new file mode 100644 index 00000000..83742e40 --- /dev/null +++ b/puppet/modules/postfwd/files/postfwd_default @@ -0,0 +1,19 @@ +### This file managed by Puppet +# Global options for postfwd(8). + +# Set to '1' to enable startup (daemon mode) +STARTUP=1 + +# Config file +CONF=/etc/postfix/postfwd.cf +# IP where listen to +INET=127.0.0.1 +# Port where listen to +PORT=10040 +# run as user postfwd +RUNAS="postfw" +# Arguments passed on start (--daemon implied) +# disable summary and cache-no-size +#ARGS="--summary=600 --cache=600 --cache-rdomain-only --cache-no-size" +ARGS="--cache=600 --cache-rdomain-only --no-rulestats" + diff --git a/puppet/modules/postfwd/manifests/init.pp b/puppet/modules/postfwd/manifests/init.pp new file mode 100644 index 00000000..6db3fa52 --- /dev/null +++ b/puppet/modules/postfwd/manifests/init.pp @@ -0,0 +1,43 @@ +# This class provides rate-limiting for outgoing SMTP, using postfwd +# it is configured with some limits that seem reasonable for a generic +# use-case. Each of the following applies to sasl_authenticated users: +# +# . 150 recipients at a time +# . no more than 50 messages in 60 minutes +# . no more than 250 recipients in 60 minutes. +# +# This class could be easily extended to add overrides to these rules, +# maximum sizes per client, or additional rules +class postfwd { + +  ensure_packages(['libnet-server-perl', 'libnet-dns-perl', 'postfwd']) + +  file { +    '/etc/default/postfwd': +      source  => 'puppet:///modules/postfwd/postfwd_default', +      mode    => '0644', +      owner   => root, +      group   => root, +      before  => Package['postfwd']; + +    '/etc/postfix/postfwd.cf': +      content => template('postfwd/postfwd.cf.erb'), +      mode    => '0644', +      owner   => root, +      group   => root, +      require => Package['postfix'], +      before  => Package['postfwd']; +  } + +  service { +    'postfwd': +      ensure     => running, +      name       => postfwd, +      pattern    => '/usr/sbin/postfwd', +      enable     => true, +      hasrestart => true, +      hasstatus  => false, +      require    => [ File['/etc/default/postfwd'], +                      File['/etc/postfix/postfwd.cf']]; +  } +} diff --git a/puppet/modules/postfwd/templates/postfwd.cf.erb b/puppet/modules/postfwd/templates/postfwd.cf.erb new file mode 100644 index 00000000..1c45dd03 --- /dev/null +++ b/puppet/modules/postfwd/templates/postfwd.cf.erb @@ -0,0 +1,28 @@ +### This file managed by Puppet +# Before deploying a rule +# 1. test with an additional "sender==test@domain.org;" in the rule so it +#   only applies to your test account +# 2. then when ready to test for all users, use WARN and watch the logs +#   for a few days and make sure it working the way you like +# 3. Then when ready to deploy for real set a proper error code + +## Overrides - make like the following example +# id=exampleuser; sasl_username==exampleuser; action=dunno + +## Rules that apply to all senders +# Recipient Per Message Limit +# We only receive mail via smtp from sasl authenticated users +# directly. We want to limit to a lower amount to prevent phished accounts +# spamming +id=RCPTSENDER; recipient_count=150; action=REJECT Too many recipients, please try again. Contact http://<%= @domain %>/tickets/new if this is in error. ERROR:RCPTSENDER  + +# Message Rate Limit +# This limits sasl authenticated users to no more than 50/60mins +# NOTE: sasl_username needs to be set to something or this check will fail +id=MSGRATE ; sasl_username=!!(^$); action==rate($$sasl_username/100/3600/450 4.7.1 exceeded message rate. Contact Contact http://<%= @domain %>/tickets/new if this is in error. ERROR:MSGRATE) + +# Total Recipient Rate Limit +# This adds up the recipients for all the sasl authenticated users messages +# and can't exceed more than 250/60min +# NOTE: sasl_username needs to be set to something or this check will fail +id=RCPTRATE ; sasl_username=!!(^$); action==rcpt($$sasl_username/500/3600/450 4.7.1 exceeded message rate. Contact http://<%= @domain %>/tickets/new if this is in error. ERROR:RCPTRATE) diff --git a/puppet/modules/resolvconf/manifests/init.pp b/puppet/modules/resolvconf/manifests/init.pp new file mode 100644 index 00000000..c22c4ea6 --- /dev/null +++ b/puppet/modules/resolvconf/manifests/init.pp @@ -0,0 +1,27 @@ +# +# resolvconf module +# +# Copyright 2008, admin(at)immerda.ch +# Copyright 2008, Puzzle ITC GmbH +# Marcel Härry haerry+puppet(at)puzzle.ch +# Simon Josi josi+puppet(at)puzzle.ch +# +# This program is free software; you can redistribute  +# it and/or modify it under the terms of the GNU  +# General Public License version 3 as published by  +# the Free Software Foundation. +# + +class resolvconf( +  $domain = $::domain,   +  $search = $::domain, +  $nameservers = [ '8.8.8.8' ] +) { +  file{'/etc/resolv.conf': +    content => $::operatingsystem ? { +      openbsd => template("resolvconf/resolvconf.${::operatingsystem}.erb"), +      default => template('resolvconf/resolvconf.erb'), +    }, +    owner => root, group => 0, mode => 0444; +  } +} diff --git a/puppet/modules/resolvconf/templates/resolvconf.OpenBSD.erb b/puppet/modules/resolvconf/templates/resolvconf.OpenBSD.erb new file mode 100644 index 00000000..48daf279 --- /dev/null +++ b/puppet/modules/resolvconf/templates/resolvconf.OpenBSD.erb @@ -0,0 +1,5 @@ +# managed by puppet +lookup file bind +<% scope.lookupvar('resolvconf::nameservers').each do |nameserver| -%> +nameserver <%= nameserver %>  +<% end -%> diff --git a/puppet/modules/resolvconf/templates/resolvconf.erb b/puppet/modules/resolvconf/templates/resolvconf.erb new file mode 100644 index 00000000..d8136bfb --- /dev/null +++ b/puppet/modules/resolvconf/templates/resolvconf.erb @@ -0,0 +1,7 @@ +# managed by puppet +domain <%= scope.lookupvar('resolvconf::domain') %> +search <%= scope.lookupvar('resolvconf::search') %> + +<% scope.lookupvar('resolvconf::nameservers').each do |nameserver| -%> +nameserver <%= nameserver %> +<% end -%> diff --git a/puppet/modules/ruby/manifests/devel.pp b/puppet/modules/ruby/manifests/devel.pp new file mode 100644 index 00000000..7068a74a --- /dev/null +++ b/puppet/modules/ruby/manifests/devel.pp @@ -0,0 +1,5 @@ +# install ruby header files and rake +class ruby::devel { +  include ruby +  ensure_packages($ruby::ruby_dev) +} diff --git a/puppet/modules/ruby/manifests/init.pp b/puppet/modules/ruby/manifests/init.pp new file mode 100644 index 00000000..8d8ae48e --- /dev/null +++ b/puppet/modules/ruby/manifests/init.pp @@ -0,0 +1,72 @@ +# Class: ruby +# +# This class installs Ruby +# +# Parameters: +# +# version: (default installed) +# Set the version of Ruby to install +# +# Sample Usage: +# +# For a standard install using the latest ruby, simply do: +# +# class { 'ruby': } +# +# On Debian this is equivilant to +# $ apt-get install ruby +# +# To install a specific version of ruby, simply do: +# +# class { 'ruby': +#    ruby_version => '1.8.7', +# } +# +# Supported versions: 1.8, 1.8.7, 1.9, 1.9.1, 1.9.3 +# +# To install the development files, you can do: +# +# class { 'ruby': install_dev => true } + +class ruby ( +  $ruby_version      = '', +  $version           = 'installed', +  $install_dev       = false +) +{ + +  case $::operatingsystem { +    'redhat', 'suse': { +      $ruby_package='ruby' +      $ruby_dev='ruby-devel' +    } +    'debian', 'ubuntu': { +      case $ruby_version { +        '1.8', '1.8.7': { +          $ruby_package = 'ruby1.8' +          $ruby_dev = [ 'ruby1.8-dev', 'rake' ] +        } +        '1.9.1': { +          $ruby_package = 'ruby1.9.1' +          $ruby_dev = [ 'ruby1.9.1-dev', 'rake' ] +        } +        '1.9', '1.9.3': { +          $ruby_package = 'ruby1.9.3' +          $ruby_dev = [ 'ruby-dev', 'rake' ] +        } +        default: { +          $ruby_package = 'ruby' +          $ruby_dev = [ 'ruby-dev', 'rake' ] +        } +      } +    } +  } + +  package{ $ruby_package: +    ensure => $version, +  } + +  if $install_dev { +    ensure_packages($ruby_dev) +  } +} diff --git a/puppet/modules/ruby/manifests/mysql.pp b/puppet/modules/ruby/manifests/mysql.pp new file mode 100644 index 00000000..2e894789 --- /dev/null +++ b/puppet/modules/ruby/manifests/mysql.pp @@ -0,0 +1,7 @@ +class ruby::mysql { +  include ruby +  package{'ruby-mysql': +    ensure => present, +    require => Package['ruby'], +  } +} diff --git a/puppet/modules/ruby/manifests/postgres.pp b/puppet/modules/ruby/manifests/postgres.pp new file mode 100644 index 00000000..ec0e253a --- /dev/null +++ b/puppet/modules/ruby/manifests/postgres.pp @@ -0,0 +1,6 @@ +class ruby::postgres { +  include ruby +  package{'ruby-postgres': +    ensure => installed, +  } +} diff --git a/puppet/modules/ruby/manifests/shadow.pp b/puppet/modules/ruby/manifests/shadow.pp new file mode 100644 index 00000000..43f1aeab --- /dev/null +++ b/puppet/modules/ruby/manifests/shadow.pp @@ -0,0 +1,6 @@ +class ruby::shadow { +  case $::operatingsystem { +    debian,ubuntu: { include ruby::shadow::debian } +    default: { include ruby::shadow::base } +  } +} diff --git a/puppet/modules/ruby/manifests/shadow/base.pp b/puppet/modules/ruby/manifests/shadow/base.pp new file mode 100644 index 00000000..af8c5c92 --- /dev/null +++ b/puppet/modules/ruby/manifests/shadow/base.pp @@ -0,0 +1,6 @@ +class ruby::shadow::base { +  require ::ruby +  package{'ruby-shadow': +    ensure => installed, +  } +} diff --git a/puppet/modules/ruby/manifests/shadow/debian.pp b/puppet/modules/ruby/manifests/shadow/debian.pp new file mode 100644 index 00000000..8182b9b1 --- /dev/null +++ b/puppet/modules/ruby/manifests/shadow/debian.pp @@ -0,0 +1,8 @@ +class ruby::shadow::debian inherits ruby::shadow::base { +  Package['ruby-shadow']{ +    name =>  $::lsbdistcodename ? { +      'wheezy' => 'libshadow-ruby1.8', +      default  => 'ruby-shadow', +    } +  } +} diff --git a/puppet/modules/rubygems/files/gemrc b/puppet/modules/rubygems/files/gemrc new file mode 100644 index 00000000..040f20ba --- /dev/null +++ b/puppet/modules/rubygems/files/gemrc @@ -0,0 +1,3 @@ +--- +:sources: +- https://rubygems.org/ diff --git a/puppet/modules/rubygems/manifests/activerecord.pp b/puppet/modules/rubygems/manifests/activerecord.pp new file mode 100644 index 00000000..131222af --- /dev/null +++ b/puppet/modules/rubygems/manifests/activerecord.pp @@ -0,0 +1,7 @@ +class rubygems::activerecord { +  require rubygems +  package{'activerecord': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/activesupport.pp b/puppet/modules/rubygems/manifests/activesupport.pp new file mode 100644 index 00000000..ae5aee70 --- /dev/null +++ b/puppet/modules/rubygems/manifests/activesupport.pp @@ -0,0 +1,7 @@ +class rubygems::activesupport { +  require rubygems +  package{'activesupport': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/backports.pp b/puppet/modules/rubygems/manifests/backports.pp new file mode 100644 index 00000000..4290e340 --- /dev/null +++ b/puppet/modules/rubygems/manifests/backports.pp @@ -0,0 +1,7 @@ +class rubygems::backports { +  require rubygems::devel +  package{'backports': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/bcrypt.pp b/puppet/modules/rubygems/manifests/bcrypt.pp new file mode 100644 index 00000000..4c646477 --- /dev/null +++ b/puppet/modules/rubygems/manifests/bcrypt.pp @@ -0,0 +1,14 @@ +class rubygems::bcrypt { +  if ($::osfamily == 'RedHat') and +    versioncmp($::operatingsystemrelease,'6') > 0 { +    package{'rubygem-bcrypt': +      ensure => present, +    } +  } else { +    require rubygems +    package{'bcrypt-ruby': +      ensure => present, +      provider => gem, +    } +  } +} diff --git a/puppet/modules/rubygems/manifests/brokengem.pp b/puppet/modules/rubygems/manifests/brokengem.pp new file mode 100644 index 00000000..b3284d97 --- /dev/null +++ b/puppet/modules/rubygems/manifests/brokengem.pp @@ -0,0 +1,14 @@ +define rubygems::brokengem($source,$ensure) { +    exec { "get-gem-$name": +        command => "/usr/bin/wget --output-document=/tmp/$name.gem $source", +        creates => "/tmp/$name.gem", +        before => Package[$name] +    } +    package{$name: +        ensure => $ensure, +        provider => gem, +        source => "/tmp/$name.gem" +    } +} + +# $Id$ diff --git a/puppet/modules/rubygems/manifests/camping.pp b/puppet/modules/rubygems/manifests/camping.pp new file mode 100644 index 00000000..f79fca13 --- /dev/null +++ b/puppet/modules/rubygems/manifests/camping.pp @@ -0,0 +1,7 @@ +class rubygems::camping { +  require rubygems::rack +  package{'camping': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/captcha/v_0_1_2.pp b/puppet/modules/rubygems/manifests/captcha/v_0_1_2.pp new file mode 100644 index 00000000..2a4e7123 --- /dev/null +++ b/puppet/modules/rubygems/manifests/captcha/v_0_1_2.pp @@ -0,0 +1,5 @@ +class rubygems::captcha::v_0_1_2 { +  rubygems::gem{ 'captcha-0.1.2': +    requiresgcc => true, +  } +} diff --git a/puppet/modules/rubygems/manifests/chronic_duration.pp b/puppet/modules/rubygems/manifests/chronic_duration.pp new file mode 100644 index 00000000..c789eb51 --- /dev/null +++ b/puppet/modules/rubygems/manifests/chronic_duration.pp @@ -0,0 +1,5 @@ +class rubygems::chronic_duration { +  rubygems::gem{'chronic_duration': +    ensure => present, +  } +} diff --git a/puppet/modules/rubygems/manifests/devel.pp b/puppet/modules/rubygems/manifests/devel.pp new file mode 100644 index 00000000..2f69f892 --- /dev/null +++ b/puppet/modules/rubygems/manifests/devel.pp @@ -0,0 +1,6 @@ +class rubygems::devel { +  include ::rubygems +  include ruby::devel +  include gcc +} + diff --git a/puppet/modules/rubygems/manifests/fastercsv.pp b/puppet/modules/rubygems/manifests/fastercsv.pp new file mode 100644 index 00000000..95ae0212 --- /dev/null +++ b/puppet/modules/rubygems/manifests/fastercsv.pp @@ -0,0 +1,6 @@ +class rubygems::fastercsv { +  rubygems::gem{'fastercsv': +    ensure => present, +    source => 'http://rubyforge.org/frs/download.php/43190/fastercsv-1.4.0.gem', +  } +} diff --git a/puppet/modules/rubygems/manifests/gd/v_0_7_4.pp b/puppet/modules/rubygems/manifests/gd/v_0_7_4.pp new file mode 100644 index 00000000..9027ecb5 --- /dev/null +++ b/puppet/modules/rubygems/manifests/gd/v_0_7_4.pp @@ -0,0 +1,5 @@ +class rubygems::gd::v_0_7_4 { +  rubygems::gem{ 'ruby-gd-0.7.4': +    buildflags => '--with-freetype', +  } +} diff --git a/puppet/modules/rubygems/manifests/gem.pp b/puppet/modules/rubygems/manifests/gem.pp new file mode 100644 index 00000000..14b67850 --- /dev/null +++ b/puppet/modules/rubygems/manifests/gem.pp @@ -0,0 +1,108 @@ +# Installs gems that are slightly broken +# As a name it expects the name of the gem. +# If you want to want to install a certain version +# you have to append the version to the gem name: +# +#    install a version of mime-types: +#       rubygems::gem{'mime-types': } +# +#    install version 0.0.4 of ruby-net-ldap: +#       rubygems::gem{'ruby-net-ldap-0.0.4': } +# +#    uninstall polygot gem (until no such gem is anymore installed): +#       rubygems::gem{'polygot': ensure => absent } +# +#    uninstall ruby-net-ldap version 0.0.3 +#       rubygems::gem{'ruby-net-ldap-0.0.3': ensure => absent } +# +# You can also set your own buildlfags, which will then install +# the gem in question by the gem command. +# +# You can also enforce to use the gem command to manage the gem +# by setting provider to `exec`. +# +define rubygems::gem( +  $ensure = 'present', +  $source = 'absent', +  $provider = 'default', +  $buildflags = 'absent', +  $requiresgcc = false +) { +  require ::rubygems +  if $requiresgcc or ($buildflags != 'absent') { +    require ::gcc +  } + +  if $name =~ /\-(\d|\.)+$/ { +    $real_name = regsubst($name,'^(.*)-(\d|\.)+$','\1') +    $gem_version = regsubst($name,'^(.*)-(\d+(\d|\.)+)$','\2') +  } else { +    $real_name = $name +  } + +  if $source != 'absent' { +    if $ensure != 'absent' { +      require rubygems::gem::cachedir +      exec{"get-gem-$name": +        command => "/usr/bin/wget -O ${rubygems::gem::cachedir::dir}/$name.gem $source", +        creates => "${rubygems::gem::cachedir::dir}/$name.gem", +      } +    } else { +      file{"${rubygems::gem::cachedir::dir}/$name.gem": +        ensure => 'absent'; +      } +    } +  } + +  if ($buildflags != 'absent') or ($provider == 'exec') { +    if $gem_version { +        $gem_version_str = "-v ${gem_version}" +        $gem_version_check_str = $gem_version +    } else { +        $gem_version_check_str = '.*' +    } + +    if $ensure == 'present' { +        $gem_cmd = 'install' +    } else { +        $gem_cmd = 'uninstall -x' +    } + +    if $buildflags != 'absent' { +      $buildflags_str = "-- --build-flags ${buildflags}" +    } else { +      $buildflags_str = '' +    } + +    exec{"manage_gem_${name}": +        command => "gem ${gem_cmd} ${real_name} ${gem_version_str} ${buildflags_str}", +    } + +    $gem_cmd_check_str = "gem list | egrep -q '^${real_name} \\(${gem_version_check_str}\\)\$'" +    if $ensure == 'present' { +        Exec["manage_gem_${name}"]{ +           unless => $gem_cmd_check_str +        } +    } else { +        Exec["manage_gem_${name}"]{ +           onlyif => $gem_cmd_check_str +        } +    } +  } else { +    package{"$real_name": +      ensure => $ensure ? { +        'absent' => $ensure, +        default => $gem_version ? { +          undef => $ensure, +          default => $gem_version +        } +      }, +      provider => gem, +    } +    if $source != 'absent' { +      Package["$name"]{ +        source => "${rubygems::gem::cachedir::dir}/$name.gem" +      } +    } +  } +} diff --git a/puppet/modules/rubygems/manifests/gem/cachedir.pp b/puppet/modules/rubygems/manifests/gem/cachedir.pp new file mode 100644 index 00000000..3e371e42 --- /dev/null +++ b/puppet/modules/rubygems/manifests/gem/cachedir.pp @@ -0,0 +1,4 @@ +class rubygems::gem::cachedir { +  $dir = '/var/lib/puppet/modules/rubygems_cache' +  modules_dir{'rubygems_cache': } +} diff --git a/puppet/modules/rubygems/manifests/gpgme.pp b/puppet/modules/rubygems/manifests/gpgme.pp new file mode 100644 index 00000000..e9b04a9a --- /dev/null +++ b/puppet/modules/rubygems/manifests/gpgme.pp @@ -0,0 +1,35 @@ +class rubygems::gpgme{ +  case $::operatingsystem { +    debian,ubuntu: { +      case $::lsbdistcodename { +        'lenny','squeeze': { +          # install gpgme as gem, as the squeeze deb-package is too old +          # for i.e. gpg module +          $provider    = 'gem' +          $packagename = 'ruby-gpgme' +          } +        default:  { +          # don't need to install gpgme as gem, debian package works +          # fine with the gpg module +          $provider    = 'apt' +          $packagename = 'libgpgme-ruby' +        } +      } +    } +    default: { +      $provider = 'gem' +      $packagename = 'ruby-gpgme' +    } +  } + +  if $provider == 'gem' { +    require rubygems::devel +    require gpg::gpgme::devel +  } + +  package{'ruby-gpgme': +    ensure   => present, +    provider => $provider, +    name     => $packagename +  } +} diff --git a/puppet/modules/rubygems/manifests/hiera.pp b/puppet/modules/rubygems/manifests/hiera.pp new file mode 100644 index 00000000..4c766a15 --- /dev/null +++ b/puppet/modules/rubygems/manifests/hiera.pp @@ -0,0 +1,7 @@ +class rubygems::hiera{ +  require ::rubygems +  package{'hiera': +    ensure => installed, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/hiera_puppet.pp b/puppet/modules/rubygems/manifests/hiera_puppet.pp new file mode 100644 index 00000000..319e7d0e --- /dev/null +++ b/puppet/modules/rubygems/manifests/hiera_puppet.pp @@ -0,0 +1,7 @@ +class rubygems::hiera_puppet { +  require rubygems::hiera +  package{'hiera-puppet': +    ensure => installed, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/highline.pp b/puppet/modules/rubygems/manifests/highline.pp new file mode 100644 index 00000000..e9da09a5 --- /dev/null +++ b/puppet/modules/rubygems/manifests/highline.pp @@ -0,0 +1,14 @@ +class rubygems::highline { +  require rubygems +  package{'rubygem-highline': +    ensure => present, +  } + +  case $::operatingsystem { +    debian,ubuntu: { +      Package['rubygem-highline']{ +        name => 'ruby-highline' +      } +    } +  } +} diff --git a/puppet/modules/rubygems/manifests/init.pp b/puppet/modules/rubygems/manifests/init.pp new file mode 100644 index 00000000..bca40b9e --- /dev/null +++ b/puppet/modules/rubygems/manifests/init.pp @@ -0,0 +1,31 @@ +# +# rubygems module +# original by luke kanies +# http://github.com/lak +# +# Copyright 2008, Puzzle ITC GmbH +# Marcel Härry haerry+puppet(at)puzzle.ch +# Simon Josi josi+puppet(at)puzzle.ch +# +# This program is free software; you can redistribute +# it and/or modify it under the terms of the GNU +# General Public License version 3 as published by +# the Free Software Foundation. +# + +# manage rubygems basics +class rubygems { +  # from debian 8 on this is not anymore needed as it's part of the ruby pkg +  if ($::operatingsystem != 'Debian') or (versioncmp($::operatingsystemrelease,'8') < 0) { +    package{'rubygems': +      ensure => installed, +    } +  } +  file { '/etc/gemrc': +    source => [ 'puppet:///modules/site_rubygems/gemrc', +                'puppet:///modules/rubygems/gemrc' ], +    mode   => '0644', +    owner  => 'root', +    group  => 'root', +  } +} diff --git a/puppet/modules/rubygems/manifests/ip.pp b/puppet/modules/rubygems/manifests/ip.pp new file mode 100644 index 00000000..190d869d --- /dev/null +++ b/puppet/modules/rubygems/manifests/ip.pp @@ -0,0 +1,7 @@ +class rubygems::ip { +  require rubygems +  package{'ip': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/json/v_1_4_6.pp b/puppet/modules/rubygems/manifests/json/v_1_4_6.pp new file mode 100644 index 00000000..d0901ba3 --- /dev/null +++ b/puppet/modules/rubygems/manifests/json/v_1_4_6.pp @@ -0,0 +1,3 @@ +class rubygems::json::v_1_4_6 { +  rubygems::gem{ 'json-1.4.6': } +} diff --git a/puppet/modules/rubygems/manifests/lockfile.pp b/puppet/modules/rubygems/manifests/lockfile.pp new file mode 100644 index 00000000..f4ed6b0f --- /dev/null +++ b/puppet/modules/rubygems/manifests/lockfile.pp @@ -0,0 +1,7 @@ +class rubygems::lockfile { +  require rubygems +  package{'lockfile': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/mail.pp b/puppet/modules/rubygems/manifests/mail.pp new file mode 100644 index 00000000..b8b50bbe --- /dev/null +++ b/puppet/modules/rubygems/manifests/mail.pp @@ -0,0 +1,19 @@ +# manage the mail rubygem +class rubygems::mail { +  if ($::osfamily == 'RedHat') and +    versioncmp($::operatingsystemrelease,'6') > 0 { +    package{'rubygem-mail': +      ensure => present, +    } +  } else { +    require rubygems::devel +    package{'mail': +      ensure   => present, +      provider => gem, +    } + +    if $::rubyversion == '1.8.6' { +      require rubygems::tlsmail +    } +  } +} diff --git a/puppet/modules/rubygems/manifests/maildir.pp b/puppet/modules/rubygems/manifests/maildir.pp new file mode 100644 index 00000000..8773f37a --- /dev/null +++ b/puppet/modules/rubygems/manifests/maildir.pp @@ -0,0 +1,15 @@ +# manage maildir rubygem +class rubygems::maildir { +  if ($::osfamily == 'RedHat') and +    versioncmp($::operatingsystemrelease,'6') > 0 { +    package{'rubygem-maildir': +      ensure => present, +    } +  } else { +    require rubygems::devel +    package{'maildir': +      ensure   => present, +      provider => gem, +    } +  } +} diff --git a/puppet/modules/rubygems/manifests/markaby.pp b/puppet/modules/rubygems/manifests/markaby.pp new file mode 100644 index 00000000..817969e3 --- /dev/null +++ b/puppet/modules/rubygems/manifests/markaby.pp @@ -0,0 +1,7 @@ +class rubygems::markaby { +  require rubygems +  package{'markaby': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/moneta.pp b/puppet/modules/rubygems/manifests/moneta.pp new file mode 100644 index 00000000..ea9bb5a6 --- /dev/null +++ b/puppet/modules/rubygems/manifests/moneta.pp @@ -0,0 +1,7 @@ +class rubygems::moneta { +  require rubygems +  package{'moneta': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/mysql.pp b/puppet/modules/rubygems/manifests/mysql.pp new file mode 100644 index 00000000..cc0bbbf6 --- /dev/null +++ b/puppet/modules/rubygems/manifests/mysql.pp @@ -0,0 +1,5 @@ +class rubygems::mysql { +    require ::mysql::devel +    require gcc +    rubygems::gem{'mysql':} +} diff --git a/puppet/modules/rubygems/manifests/net_ldap/v_0_0_4.pp b/puppet/modules/rubygems/manifests/net_ldap/v_0_0_4.pp new file mode 100644 index 00000000..88e1e7b4 --- /dev/null +++ b/puppet/modules/rubygems/manifests/net_ldap/v_0_0_4.pp @@ -0,0 +1,3 @@ +class rubygems::net_ldap::v_0_0_4 { +  rubygems::gem{ 'ruby-net-ldap-0.0.4': } +} diff --git a/puppet/modules/rubygems/manifests/ntlm/v_0_1_1.pp b/puppet/modules/rubygems/manifests/ntlm/v_0_1_1.pp new file mode 100644 index 00000000..fd6eade3 --- /dev/null +++ b/puppet/modules/rubygems/manifests/ntlm/v_0_1_1.pp @@ -0,0 +1,3 @@ +class rubygems::ntlm::v_0_1_1 { +  rubygems::gem{ 'rubyntlm-0.1.1': } +} diff --git a/puppet/modules/rubygems/manifests/open4.pp b/puppet/modules/rubygems/manifests/open4.pp new file mode 100644 index 00000000..1e3fbb78 --- /dev/null +++ b/puppet/modules/rubygems/manifests/open4.pp @@ -0,0 +1,7 @@ +class rubygems::open4 { +  require rubygems +  package{'open4': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/pbkdf2.pp b/puppet/modules/rubygems/manifests/pbkdf2.pp new file mode 100644 index 00000000..b2cf1136 --- /dev/null +++ b/puppet/modules/rubygems/manifests/pbkdf2.pp @@ -0,0 +1,8 @@ +class rubygems::pbkdf2{ +  require ::rubygems +  package{'pbkdf2': +    ensure => installed, +    provider => gem, +  } +} + diff --git a/puppet/modules/rubygems/manifests/postgres.pp b/puppet/modules/rubygems/manifests/postgres.pp new file mode 100644 index 00000000..8720f4ef --- /dev/null +++ b/puppet/modules/rubygems/manifests/postgres.pp @@ -0,0 +1,11 @@ +class rubygems::postgres { +  if $::osfamily == 'RedHat' and +    versioncmp($::operatingsystemrelease,'5') > 0 { +    package{'rubygem-pg': +      ensure => installed, +    } +  } else { +    require postgres::devel +    rubygems::gem{'ruby-pg':} +  } +} diff --git a/puppet/modules/rubygems/manifests/rack.pp b/puppet/modules/rubygems/manifests/rack.pp new file mode 100644 index 00000000..953ab22b --- /dev/null +++ b/puppet/modules/rubygems/manifests/rack.pp @@ -0,0 +1,7 @@ +class rubygems::rack { +  require rubygems +  package{'rack': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/sinatra.pp b/puppet/modules/rubygems/manifests/sinatra.pp new file mode 100644 index 00000000..327f829f --- /dev/null +++ b/puppet/modules/rubygems/manifests/sinatra.pp @@ -0,0 +1,7 @@ +class rubygems::sinatra { +  require rubygems +  package{'sinatra': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/sqlite.pp b/puppet/modules/rubygems/manifests/sqlite.pp new file mode 100644 index 00000000..6b670152 --- /dev/null +++ b/puppet/modules/rubygems/manifests/sqlite.pp @@ -0,0 +1,6 @@ +class rubygems::sqlite { +  require rubygems::devel +  package{'rubygem-sqlite3-ruby': +    ensure => present, +  } +} diff --git a/puppet/modules/rubygems/manifests/systemu.pp b/puppet/modules/rubygems/manifests/systemu.pp new file mode 100644 index 00000000..62a599cf --- /dev/null +++ b/puppet/modules/rubygems/manifests/systemu.pp @@ -0,0 +1,7 @@ +class rubygems::systemu { +  require rubygems +  package{'systemu': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/thin.pp b/puppet/modules/rubygems/manifests/thin.pp new file mode 100644 index 00000000..b2499d81 --- /dev/null +++ b/puppet/modules/rubygems/manifests/thin.pp @@ -0,0 +1,7 @@ +class rubygems::thin { +  require rubygems +  package{'thin': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/tlsmail.pp b/puppet/modules/rubygems/manifests/tlsmail.pp new file mode 100644 index 00000000..71aa6158 --- /dev/null +++ b/puppet/modules/rubygems/manifests/tlsmail.pp @@ -0,0 +1,7 @@ +class rubygems::tlsmail { +  require rubygems::devel +  package{'tlsmail': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/tmail.pp b/puppet/modules/rubygems/manifests/tmail.pp new file mode 100644 index 00000000..dd7117d9 --- /dev/null +++ b/puppet/modules/rubygems/manifests/tmail.pp @@ -0,0 +1,7 @@ +class rubygems::tmail { +  require rubygems::devel +  package{'tmail': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/xmlsimple.pp b/puppet/modules/rubygems/manifests/xmlsimple.pp new file mode 100644 index 00000000..914156b0 --- /dev/null +++ b/puppet/modules/rubygems/manifests/xmlsimple.pp @@ -0,0 +1,20 @@ +# xml simple lib +class rubygems::xmlsimple { +  package{'rubygem-xml-simple': +    ensure => present, +  } +  case $::operatingsystem { +    debian,ubuntu: { +      Package['rubygem-xml-simple']{ +        name => 'libxml-simple-ruby' +      } +    } +  } +  if $::operatingsystem == 'CentOS' and versioncmp($::operatingsystemrelease, '6') > 0 { +    # not yet packaged +    Package['rubygem-xml-simple']{ +      name     => 'xml-simple', +      provider => gem, +    } +  } +} diff --git a/puppet/modules/rubygems/manifests/xmpp4r.pp b/puppet/modules/rubygems/manifests/xmpp4r.pp new file mode 100644 index 00000000..068d5825 --- /dev/null +++ b/puppet/modules/rubygems/manifests/xmpp4r.pp @@ -0,0 +1,7 @@ +class rubygems::xmpp4r { +  require ::rubygems +  package{'xmpp4r': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/rubygems/manifests/ya2yaml.pp b/puppet/modules/rubygems/manifests/ya2yaml.pp new file mode 100644 index 00000000..7df362dc --- /dev/null +++ b/puppet/modules/rubygems/manifests/ya2yaml.pp @@ -0,0 +1,7 @@ +class rubygems::ya2yaml { +  require rubygems +  package{'ya2yaml': +    ensure => present, +    provider => gem, +  } +} diff --git a/puppet/modules/shorewall/LICENSE b/puppet/modules/shorewall/LICENSE new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/puppet/modules/shorewall/LICENSE @@ -0,0 +1,674 @@ +                    GNU GENERAL PUBLIC LICENSE +                       Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +                            Preamble + +  The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +  The licenses for most software and other practical works are designed +to take away your freedom to share and change the works.  By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users.  We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors.  You can apply it to +your programs, too. + +  When we speak of free software, we are referring to freedom, not +price.  Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +  To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights.  Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received.  You must make sure that they, too, receive +or can get the source code.  And you must show them these terms so they +know their rights. + +  Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +  For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software.  For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +  Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so.  This is fundamentally incompatible with the aim of +protecting users' freedom to change the software.  The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable.  Therefore, we +have designed this version of the GPL to prohibit the practice for those +products.  If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + +  Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary.  To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + +  The precise terms and conditions for copying, distribution and +modification follow. + +                       TERMS AND CONDITIONS + +  0. Definitions. + +  "This License" refers to version 3 of the GNU General Public License. + +  "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +  "The Program" refers to any copyrightable work licensed under this +License.  Each licensee is addressed as "you".  "Licensees" and +"recipients" may be individuals or organizations. + +  To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy.  The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + +  A "covered work" means either the unmodified Program or a work based +on the Program. + +  To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy.  Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +  To "convey" a work means any kind of propagation that enables other +parties to make or receive copies.  Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +  An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License.  If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +  1. Source Code. + +  The "source code" for a work means the preferred form of the work +for making modifications to it.  "Object code" means any non-source +form of a work. + +  A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +  The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form.  A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +  The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities.  However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work.  For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +  The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +  The Corresponding Source for a work in source code form is that +same work. + +  2. Basic Permissions. + +  All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met.  This License explicitly affirms your unlimited +permission to run the unmodified Program.  The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work.  This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +  You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force.  You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright.  Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +  Conveying under any other circumstances is permitted solely under +the conditions stated below.  Sublicensing is not allowed; section 10 +makes it unnecessary. + +  3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +  No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +  When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +  4. Conveying Verbatim Copies. + +  You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +  You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +  5. Conveying Modified Source Versions. + +  You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +    a) The work must carry prominent notices stating that you modified +    it, and giving a relevant date. + +    b) The work must carry prominent notices stating that it is +    released under this License and any conditions added under section +    7.  This requirement modifies the requirement in section 4 to +    "keep intact all notices". + +    c) You must license the entire work, as a whole, under this +    License to anyone who comes into possession of a copy.  This +    License will therefore apply, along with any applicable section 7 +    additional terms, to the whole of the work, and all its parts, +    regardless of how they are packaged.  This License gives no +    permission to license the work in any other way, but it does not +    invalidate such permission if you have separately received it. + +    d) If the work has interactive user interfaces, each must display +    Appropriate Legal Notices; however, if the Program has interactive +    interfaces that do not display Appropriate Legal Notices, your +    work need not make them do so. + +  A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit.  Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +  6. Conveying Non-Source Forms. + +  You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +    a) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by the +    Corresponding Source fixed on a durable physical medium +    customarily used for software interchange. + +    b) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by a +    written offer, valid for at least three years and valid for as +    long as you offer spare parts or customer support for that product +    model, to give anyone who possesses the object code either (1) a +    copy of the Corresponding Source for all the software in the +    product that is covered by this License, on a durable physical +    medium customarily used for software interchange, for a price no +    more than your reasonable cost of physically performing this +    conveying of source, or (2) access to copy the +    Corresponding Source from a network server at no charge. + +    c) Convey individual copies of the object code with a copy of the +    written offer to provide the Corresponding Source.  This +    alternative is allowed only occasionally and noncommercially, and +    only if you received the object code with such an offer, in accord +    with subsection 6b. + +    d) Convey the object code by offering access from a designated +    place (gratis or for a charge), and offer equivalent access to the +    Corresponding Source in the same way through the same place at no +    further charge.  You need not require recipients to copy the +    Corresponding Source along with the object code.  If the place to +    copy the object code is a network server, the Corresponding Source +    may be on a different server (operated by you or a third party) +    that supports equivalent copying facilities, provided you maintain +    clear directions next to the object code saying where to find the +    Corresponding Source.  Regardless of what server hosts the +    Corresponding Source, you remain obligated to ensure that it is +    available for as long as needed to satisfy these requirements. + +    e) Convey the object code using peer-to-peer transmission, provided +    you inform other peers where the object code and Corresponding +    Source of the work are being offered to the general public at no +    charge under subsection 6d. + +  A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +  A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling.  In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage.  For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product.  A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +  "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source.  The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +  If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information.  But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +  The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed.  Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +  Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +  7. Additional Terms. + +  "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law.  If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +  When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it.  (Additional permissions may be written to require their own +removal in certain cases when you modify the work.)  You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +  Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +    a) Disclaiming warranty or limiting liability differently from the +    terms of sections 15 and 16 of this License; or + +    b) Requiring preservation of specified reasonable legal notices or +    author attributions in that material or in the Appropriate Legal +    Notices displayed by works containing it; or + +    c) Prohibiting misrepresentation of the origin of that material, or +    requiring that modified versions of such material be marked in +    reasonable ways as different from the original version; or + +    d) Limiting the use for publicity purposes of names of licensors or +    authors of the material; or + +    e) Declining to grant rights under trademark law for use of some +    trade names, trademarks, or service marks; or + +    f) Requiring indemnification of licensors and authors of that +    material by anyone who conveys the material (or modified versions of +    it) with contractual assumptions of liability to the recipient, for +    any liability that these contractual assumptions directly impose on +    those licensors and authors. + +  All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10.  If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term.  If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +  If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +  Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +  8. Termination. + +  You may not propagate or modify a covered work except as expressly +provided under this License.  Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +  However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +  Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +  Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License.  If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +  9. Acceptance Not Required for Having Copies. + +  You are not required to accept this License in order to receive or +run a copy of the Program.  Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance.  However, +nothing other than this License grants you permission to propagate or +modify any covered work.  These actions infringe copyright if you do +not accept this License.  Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +  10. Automatic Licensing of Downstream Recipients. + +  Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License.  You are not responsible +for enforcing compliance by third parties with this License. + +  An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations.  If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +  You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License.  For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +  11. Patents. + +  A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based.  The +work thus licensed is called the contributor's "contributor version". + +  A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version.  For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +  Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +  In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement).  To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +  If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients.  "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +  If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +  A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License.  You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +  Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +  12. No Surrender of Others' Freedom. + +  If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License.  If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all.  For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +  13. Use with the GNU Affero General Public License. + +  Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work.  The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +  14. Revised Versions of this License. + +  The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time.  Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +  Each version is given a distinguishing version number.  If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation.  If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + +  If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +  Later license versions may give you additional or different +permissions.  However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +  15. Disclaimer of Warranty. + +  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +  16. Limitation of Liability. + +  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +  17. Interpretation of Sections 15 and 16. + +  If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +                     END OF TERMS AND CONDITIONS + +            How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + +    <one line to give the program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    This program is free software: you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation, either version 3 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program.  If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + +  If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +    <program>  Copyright (C) <year>  <name of author> +    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + +  You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + +  The GNU General Public License does not permit incorporating your program +into proprietary programs.  If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library.  If this is what you want to do, use the GNU Lesser General +Public License instead of this License.  But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/puppet/modules/shorewall/README b/puppet/modules/shorewall/README new file mode 100644 index 00000000..3a84b3bd --- /dev/null +++ b/puppet/modules/shorewall/README @@ -0,0 +1,219 @@ +modules/shorewall/manifests/init.pp - manage firewalling with shorewall 3.x + +Puppet Module for Shorewall +--------------------------- +This module manages the configuration of Shorewall (http://www.shorewall.net/) + +Requirements +------------ + +This module requires the augeas module, you can find that here: +https://labs.riseup.net/code/projects/shared-augeas + +Copyright +--------- + +Copyright (C) 2007 David Schmitt <david@schmitt.edv-bus.at> +adapted by immerda project group - admin+puppet(at)immerda.ch +adapted by Puzzle ITC - haerry+puppet(at)puzzle.ch +Copyright (c) 2009 Riseup Networks - micah(shift+2)riseup.net +Copyright (c) 2010 intrigeri - intrigeri(at)boum.org +See LICENSE for the full license granted to you. + +Based on the work of ADNET Ghislain <gadnet@aqueos.com> from AQUEOS +at https://reductivelabs.com/trac/puppet/wiki/AqueosShorewall + +Merged from: +- git://git.puppet.immerda.ch/module-shorewall.git +- git://labs.riseup.net/module_shorewall + +Todo +---- +- check if shorewall compiles without errors, otherwise fail ! + +Configuration +------------- + +If you need to install a specific version of shorewall other than +the default one that would be installed by 'ensure => present', then +you can set the following variable and that specific version will be +installed instead: + +    $shorewall_ensure_version = "4.0.15-1" + +The main shorewall.conf is not managed by this module, rather the default one +that your operatingsystem provides is used, and any modifications you wish to do +to it should be configured with augeas, for example, to set IP_FORWARDING=Yes in +shorewall.conf, simply do this: + +  augeas { 'enable_ip_forwarding': +    changes => 'set /files/etc/shorewall/shorewall.conf/IP_FORWARDING Yes', +    lens    => 'Shellvars.lns', +    incl    => '/etc/shorewall/shorewall.conf', +    notify  => Service[shorewall]; +  } + +NOTE: this requires the augeas ruby bindings newer than 0.7.3.  + +If you need to, you can provide an entire shorewall.conf by passing its +source to the main class: + +class{'shorewall': +  conf_source => "puppet:///modules/site_shorewall/${::fqdn}/shorewall.conf.${::operatingsystem}", +} + +NOTE: if you distribute a file, you cannot also use augeas, puppet and augeas +will fight forever. Secondly, you will *need* to make sure that if you are shipping your own +shorewall.conf that you have the following value set in your shorewall.conf otherwise this +module will not work: + +    CONFIG_PATH="/etc/shorewall/puppet:/etc/shorewall:/usr/share/shorewall" + +Documentation +------------- + +see also: http://reductivelabs.com/trac/puppet/wiki/Recipes/AqueosShorewall + +Torify +------ + +The shorewall::rules::torify define can be used to force some outgoing +TCP traffic through the Tor transparent proxy. The corresponding +non-TCP traffic is rejected accordingly. + +Beware! This define only is part of a torified setup. DNS requests and +IPv6, amongst others, might leak network activity you would prefer not +to. You really need to read proper documentation about these matters +before using this feature e.g.: + +  https://www.torproject.org/download/download.html.en#warning + +The Tor transparent proxy location defaults to 127.0.0.1:9040 and can +be configured by setting the $tor_transparent_proxy_host and +$tor_transparent_proxy_port variables before including the main +shorewall class. + +Example usage follows. + +Torify any outgoing TCP traffic originating from user bob or alice and +aimed at 6.6.6.6 or 7.7.7.7: + +  shorewall::rules::torify { +    'torify-some-bits': +      users        => [ 'bob', 'alice' ], +      destinations => [ '6.6.6.6', '7.7.7.7' ]; +  } + +Torify any outgoing TCP traffic to 8.8.8.8: + +  shorewall::rules::torify { +    'torify-to-this-host': +      destinations  => [ '8.8.8.8' ]; +  } + +When no destination nor user is provided any outgoing TCP traffic (see +restrictions bellow) is torified. In that case the user running the +Tor client ($tor_user) is whitelisted; this variable defaults to +"debian-tor" on Debian systems and to "tor" on others. if this does +not suit your configuration you need to set the $tor_user variable +before including the main shorewall class. + +When no destination is provided traffic directed to RFC1918 addresses +is by default allowed and (obviously) not torified. This behaviour can +be changed by setting the allow_rfc1918 parameter to false. + +Torify any outgoing TCP traffic but connections to RFC1918 addresses: + +  shorewall::rules::torify { +    'torify-everything-but-lan': +  } + +Torify any outgoing TCP traffic: + +  shorewall::rules::torify { +    'torify-everything: +      allow_rfc1918 => false; +  } + +In some cases (e.g. when providing no specific destination nor user +and denying access to RFC1918 addresses) UDP DNS requests may be +rejected. This is intentional: it does not make sense leaking -via DNS +requests- network activity that would otherwise be torified. In that +case you probably want to read proper documentation about such +matters, enable the Tor DNS resolver and redirect DNS requests through +it. + +Example +------- + +Example from node.pp: + +node xy { +	class{'config::site_shorewall': +	  startup => "0"  # create shorewall ruleset but don't startup +  } +	shorewall::rule { +		'incoming-ssh': source => 'all', destination => '$FW',  action  => 'SSH(ACCEPT)', order => 200; +		'incoming-puppetmaster': source => 'all', destination => '$FW',  action  => 'Puppetmaster(ACCEPT)', order => 300; +		'incoming-imap': source => 'all', destination => '$FW',  action  => 'IMAP(ACCEPT)', order => 300; +		'incoming-smtp': source => 'all', destination => '$FW',  action  => 'SMTP(ACCEPT)', order => 300; +	} +} + + +class config::site_shorewall($startup = '1') { +  class{'shorewall': +    startup => $startup +  } + +  # If you want logging: +  #shorewall::params { +  # 'LOG':  value => 'debug'; +  #} + +  shorewall::zone {'net': +    type => 'ipv4'; +  } + +  shorewall::rule_section { 'NEW': +    order => 100; +  } + +  shorewall::interface { 'eth0': +    zone    => 'net', +    rfc1918  => true, +    options => 'tcpflags,blacklist,nosmurfs'; +  } + +  shorewall::policy { +    'fw-to-fw': +      sourcezone              =>      '$FW', +      destinationzone         =>      '$FW', +      policy                  =>      'ACCEPT', +      order                   =>      100; +    'fw-to-net': +      sourcezone              =>      '$FW', +      destinationzone         =>      'net', +      policy                  =>      'ACCEPT', +      shloglevel              =>      '$LOG', +      order                   =>      110; +    'net-to-fw': +      sourcezone              =>      'net', +      destinationzone         =>      '$FW', +      policy                  =>      'DROP', +      shloglevel              =>      '$LOG', +      order                   =>      120; +  }        + +         +  # default Rules : ICMP  +  shorewall::rule { +    'allicmp-to-host': +      source => 'all', +      destination => '$FW', +      order  => 200, +      action  => 'AllowICMPs/(ACCEPT)'; +  } +} + + diff --git a/puppet/modules/shorewall/files/boilerplate/blacklist.footer b/puppet/modules/shorewall/files/boilerplate/blacklist.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/blacklist.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/blacklist.header b/puppet/modules/shorewall/files/boilerplate/blacklist.header new file mode 100644 index 00000000..2392e176 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/blacklist.header @@ -0,0 +1,10 @@ +# +# Shorewall version 3.4 - Blacklist File +# +# For information about entries in this file, type "man shorewall-blacklist" +# +# Please see http://shorewall.net/blacklisting_support.htm for additional +# information. +# +############################################################################### +#ADDRESS/SUBNET         PROTOCOL        PORT diff --git a/puppet/modules/shorewall/files/boilerplate/clear.footer b/puppet/modules/shorewall/files/boilerplate/clear.footer new file mode 100644 index 00000000..662ac1cc --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/clear.footer @@ -0,0 +1 @@ +#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/clear.header b/puppet/modules/shorewall/files/boilerplate/clear.header new file mode 100644 index 00000000..6a39b0b6 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/clear.header @@ -0,0 +1,13 @@ +# +# Shorewall version 4 - Clear +# +# /etc/shorewall/stop +# +#       Add commands below that you want to be executed at the beginning of a +#       "shorewall stop" command. +# +# See http://shorewall.net/shorewall_extension_scripts.htm for additional +# information. +# +############################################################################### +#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/continue.footer b/puppet/modules/shorewall/files/boilerplate/continue.footer new file mode 100644 index 00000000..662ac1cc --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/continue.footer @@ -0,0 +1 @@ +#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/continue.header b/puppet/modules/shorewall/files/boilerplate/continue.header new file mode 100644 index 00000000..d2ee48a5 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/continue.header @@ -0,0 +1,14 @@ +# +# Shorewall version 4 - Continue File +# +#  /etc/shorewall/continue +# +#	Add commands below that you want to be executed after shorewall has +#	cleared any existing Netfilter rules and has enabled existing +#	connections. +# +# For additional information, see +# http://shorewall.net/shorewall_extension_scripts.htm +# +############################################################################### + diff --git a/puppet/modules/shorewall/files/boilerplate/hosts.footer b/puppet/modules/shorewall/files/boilerplate/hosts.footer new file mode 100644 index 00000000..dc2fef52 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/hosts.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS LINE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/hosts.header b/puppet/modules/shorewall/files/boilerplate/hosts.header new file mode 100644 index 00000000..e39d6145 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/hosts.header @@ -0,0 +1,9 @@ +# +# Shorewall version 3.4 - Hosts file +# +# For information about entries in this file, type "man shorewall-hosts" +# +# For additional information, see http://shorewall.net/Documentation.htm#Hosts +# +############################################################################### +#ZONE   HOST(S)                                 OPTIONS diff --git a/puppet/modules/shorewall/files/boilerplate/init.footer b/puppet/modules/shorewall/files/boilerplate/init.footer new file mode 100644 index 00000000..662ac1cc --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/init.footer @@ -0,0 +1 @@ +#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/init.header b/puppet/modules/shorewall/files/boilerplate/init.header new file mode 100644 index 00000000..cbb0393e --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/init.header @@ -0,0 +1,13 @@ +# +# Shorewall version 4 - Init File +# +# /etc/shorewall/init +# +#	Add commands below that you want to be executed at the beginning of +#	a "shorewall start" or "shorewall restart" command. +# +# For additional information, see +# http://shorewall.net/shorewall_extension_scripts.htm +# +############################################################################### + diff --git a/puppet/modules/shorewall/files/boilerplate/initdone.footer b/puppet/modules/shorewall/files/boilerplate/initdone.footer new file mode 100644 index 00000000..662ac1cc --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/initdone.footer @@ -0,0 +1 @@ +#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/initdone.header b/puppet/modules/shorewall/files/boilerplate/initdone.header new file mode 100644 index 00000000..9252a3bc --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/initdone.header @@ -0,0 +1,14 @@ +# +# Shorewall version 4 - Initdone File +# +# /etc/shorewall/initdone +# +#	Add commands below that you want to be executed during +#	"shorewall start" or "shorewall restart" commands at the point where +#	Shorewall has not yet added any perminent rules to the builtin chains. +# +# For additional information, see +# http://shorewall.net/shorewall_extension_scripts.htm +# +############################################################################### + diff --git a/puppet/modules/shorewall/files/boilerplate/interfaces.footer b/puppet/modules/shorewall/files/boilerplate/interfaces.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/interfaces.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/interfaces.header b/puppet/modules/shorewall/files/boilerplate/interfaces.header new file mode 100644 index 00000000..2027523e --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/interfaces.header @@ -0,0 +1,10 @@ +# +# Shorewall version 3.4 - Interfaces File +# +# For information about entries in this file, type "man shorewall-interfaces" +# +# For additional information, see +# http://shorewall.net/Documentation.htm#Interfaces +# +############################################################################### +#ZONE   INTERFACE       BROADCAST       OPTIONS diff --git a/puppet/modules/shorewall/files/boilerplate/maclog.footer b/puppet/modules/shorewall/files/boilerplate/maclog.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/maclog.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/maclog.header b/puppet/modules/shorewall/files/boilerplate/maclog.header new file mode 100644 index 00000000..b0c382ab --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/maclog.header @@ -0,0 +1,14 @@ +# +# Shorewall version 4 - Maclog File (Added in Shorewall version 3.2.5) +# +# /etc/shorewall/start +# +#	Add commands below that you want executed while mac filtering rules are +#	being created. These will be executed once for each interface having +#	'maclist' speciied and it is invoked just before the logging rule is  +#	added to the current chain (the name of that chain will be in $CHAIN) +# +# See http://shorewall.net/shorewall_extension_scripts.htm for additional +# information. +# +############################################################################### diff --git a/puppet/modules/shorewall/files/boilerplate/mangle.footer b/puppet/modules/shorewall/files/boilerplate/mangle.footer new file mode 100644 index 00000000..6bebc05c --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/mangle.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES ABOVE THIS LINE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/mangle.header b/puppet/modules/shorewall/files/boilerplate/mangle.header new file mode 100644 index 00000000..7a7b12ab --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/mangle.header @@ -0,0 +1,7 @@ +# +# Shorewall - Mangle File +# +# For additional information, see http://shorewall.net/manpages/shorewall-mangle.html +# +####################################################################################### +#ACTION SOURCE DESTINATION PROTO DSTPORT SRCPORT USER TEST LENGTH TOS CONNBYTES HELPER HEADERS diff --git a/puppet/modules/shorewall/files/boilerplate/masq.footer b/puppet/modules/shorewall/files/boilerplate/masq.footer new file mode 100644 index 00000000..6bebc05c --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/masq.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES ABOVE THIS LINE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/masq.header b/puppet/modules/shorewall/files/boilerplate/masq.header new file mode 100644 index 00000000..f8233210 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/masq.header @@ -0,0 +1,9 @@ +# +# Shorewall version 3.4 - Masq file +# +# For information about entries in this file, type "man shorewall-masq" +# +# For additional information, see http://shorewall.net/Documentation.htm#Masq +# +############################################################################### +#INTERFACE              SOURCE          ADDRESS         PROTO   PORT(S) IPSEC   MARK diff --git a/puppet/modules/shorewall/files/boilerplate/nat.footer b/puppet/modules/shorewall/files/boilerplate/nat.footer new file mode 100644 index 00000000..6bebc05c --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/nat.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES ABOVE THIS LINE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/nat.header b/puppet/modules/shorewall/files/boilerplate/nat.header new file mode 100644 index 00000000..c2e0d922 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/nat.header @@ -0,0 +1,9 @@ +# +# Shorewall version 3.4 - Nat File +# +# For information about entries in this file, type "man shorewall-nat" +# +# For additional information, see http://shorewall.net/NAT.htm +# +############################################################################### +#EXTERNAL       INTERFACE       INTERNAL        ALL             LOCAL diff --git a/puppet/modules/shorewall/files/boilerplate/params.footer b/puppet/modules/shorewall/files/boilerplate/params.footer new file mode 100644 index 00000000..662ac1cc --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/params.footer @@ -0,0 +1 @@ +#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/params.header b/puppet/modules/shorewall/files/boilerplate/params.header new file mode 100644 index 00000000..b258b0de --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/params.header @@ -0,0 +1,26 @@ +# +# Shorewall version 3.4 - Params File +# +# /etc/shorewall/params +# +#       Assign any variables that you need here. +# +#       It is suggested that variable names begin with an upper case letter +#       to distinguish them from variables used internally within the +#       Shorewall programs +# +#       Example: +# +#               NET_IF=eth0 +#               NET_BCAST=130.252.100.255 +#               NET_OPTIONS=routefilter,norfc1918 +# +#       Example (/etc/shorewall/interfaces record): +# +#               net     $NET_IF         $NET_BCAST      $NET_OPTIONS +# +#       The result will be the same as if the record had been written +# +#               net     eth0            130.252.100.255 routefilter,norfc1918 +# +############################################################################### diff --git a/puppet/modules/shorewall/files/boilerplate/policy.footer b/puppet/modules/shorewall/files/boilerplate/policy.footer new file mode 100644 index 00000000..16c86d0e --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/policy.footer @@ -0,0 +1 @@ +#LAST LINE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/policy.header b/puppet/modules/shorewall/files/boilerplate/policy.header new file mode 100644 index 00000000..a0c5d5d2 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/policy.header @@ -0,0 +1,9 @@ +# +# Shorewall version 3.4 - Policy File +# +# For information about entries in this file, type "man shorewall-policy" +# +# See http://shorewall.net/Documentation.htm#Policy for additional information. +# +############################################################################### +#SOURCE         DEST            POLICY          LOG             LIMIT:BURST diff --git a/puppet/modules/shorewall/files/boilerplate/providers.footer b/puppet/modules/shorewall/files/boilerplate/providers.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/providers.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/providers.header b/puppet/modules/shorewall/files/boilerplate/providers.header new file mode 100644 index 00000000..b4a5990f --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/providers.header @@ -0,0 +1,9 @@ +# +# Shorewall version 4 - Providers File +# +# For information about entries in this file, type "man shorewall-providers" +# +# For additional information, see http://shorewall.net/MultiISP.html +# +############################################################################################ +#NAME	NUMBER	MARK	DUPLICATE	INTERFACE	GATEWAY		OPTIONS		COPY diff --git a/puppet/modules/shorewall/files/boilerplate/proxyarp.footer b/puppet/modules/shorewall/files/boilerplate/proxyarp.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/proxyarp.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/proxyarp.header b/puppet/modules/shorewall/files/boilerplate/proxyarp.header new file mode 100644 index 00000000..1e168532 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/proxyarp.header @@ -0,0 +1,9 @@ +# +# Shorewall version  3.4 - Proxyarp File +# +# For information about entries in this file, type "man shorewall-proxyarp" +# +# See http://shorewall.net/ProxyARP.htm for additional information. +# +############################################################################### +#ADDRESS        INTERFACE       EXTERNAL        HAVEROUTE       PERSISTENT diff --git a/puppet/modules/shorewall/files/boilerplate/rfc1918.footer b/puppet/modules/shorewall/files/boilerplate/rfc1918.footer new file mode 100644 index 00000000..e07fdb15 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/rfc1918.footer @@ -0,0 +1,5 @@ +# The real subnets from RFC1918 +172.16.0.0/12           logdrop         # RFC 1918 +192.168.0.0/16          logdrop         # RFC 1918 +10.0.0.0/8              logdrop         # RFC 1918 +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/rfc1918.header b/puppet/modules/shorewall/files/boilerplate/rfc1918.header new file mode 100644 index 00000000..8d6a4162 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/rfc1918.header @@ -0,0 +1,5 @@ +# +# Shorewall version 3.4 - Rfc1918 File +# +############################################################################### +#SUBNETS                TARGET diff --git a/puppet/modules/shorewall/files/boilerplate/routestopped.footer b/puppet/modules/shorewall/files/boilerplate/routestopped.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/routestopped.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/routestopped.header b/puppet/modules/shorewall/files/boilerplate/routestopped.header new file mode 100644 index 00000000..5408aace --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/routestopped.header @@ -0,0 +1,11 @@ +# +# Shorewall version 3.4 - Routestopped File +# +# For information about entries in this file, type "man shorewall-routestopped" +# +# See http://shorewall.net/Documentation.htm#Routestopped and +# http://shorewall.net/starting_and_stopping_shorewall.htm for additional +# information. +# +############################################################################### +#INTERFACE      HOST(S)                 OPTIONS diff --git a/puppet/modules/shorewall/files/boilerplate/rtrules.footer b/puppet/modules/shorewall/files/boilerplate/rtrules.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/rtrules.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/rtrules.header b/puppet/modules/shorewall/files/boilerplate/rtrules.header new file mode 100644 index 00000000..fd9b2f48 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/rtrules.header @@ -0,0 +1,8 @@ +# +# Shorewall version 4 - route rules File +# +# For information about entries in this file, type "man shorewall-rtrules" +# +# For additional information, see http://www.shorewall.net/MultiISP.html +#################################################################################### +# SOURCE DEST PROVIDER PRIORITY MASK  diff --git a/puppet/modules/shorewall/files/boilerplate/rules.footer b/puppet/modules/shorewall/files/boilerplate/rules.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/rules.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/rules.header b/puppet/modules/shorewall/files/boilerplate/rules.header new file mode 100644 index 00000000..764358ac --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/rules.header @@ -0,0 +1,10 @@ +# +# Shorewall version 3.4 - Rules File +# +# For information on the settings in this file, type "man shorewall-rules" +# +# See http://shorewall.net/Documentation.htm#Rules for additional information. +# +############################################################################################################# +#ACTION SOURCE          DEST            PROTO   DEST    SOURCE          ORIGINAL        RATE            USER/   MARK +#                                               PORT    PORT(S)         DEST            LIMIT           GROUP diff --git a/puppet/modules/shorewall/files/boilerplate/start.footer b/puppet/modules/shorewall/files/boilerplate/start.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/start.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/start.header b/puppet/modules/shorewall/files/boilerplate/start.header new file mode 100644 index 00000000..689dff19 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/start.header @@ -0,0 +1,12 @@ +# +# Shorewall version 4 - Start File +# +# /etc/shorewall/start +# +#	Add commands below that you want to be executed after shorewall has +#	been started or restarted. +# +# See http://shorewall.net/shorewall_extension_scripts.htm for additional +# information. +# +############################################################################### diff --git a/puppet/modules/shorewall/files/boilerplate/started.footer b/puppet/modules/shorewall/files/boilerplate/started.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/started.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/started.header b/puppet/modules/shorewall/files/boilerplate/started.header new file mode 100644 index 00000000..b7704dba --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/started.header @@ -0,0 +1,20 @@ +# +# Shorewall version 4 - Started File +# +# /etc/shorewall/started +# +#	Add commands below that you want to be executed after shorewall has +#	been completely started or restarted. The difference between this +#	extension script and /etc/shorewall/start is that this one is invoked +#	after delayed loading of the blacklist (DELAYBLACKLISTLOAD=Yes) and +#	after the 'shorewall' chain has been created (thus signaling that the +#	firewall is completely up). +# +#	This script should not change the firewall configuration directly but +#	may do so indirectly by running /sbin/shorewall with the 'nolock' +#	option. +# +# See http://shorewall.net/shorewall_extension_scripts.htm for additional +# information. +# +############################################################################### diff --git a/puppet/modules/shorewall/files/boilerplate/stop.footer b/puppet/modules/shorewall/files/boilerplate/stop.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/stop.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/stop.header b/puppet/modules/shorewall/files/boilerplate/stop.header new file mode 100644 index 00000000..0088abe1 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/stop.header @@ -0,0 +1,13 @@ +# +# Shorewall version 4 - Stop File +# +# /etc/shorewall/stop +# +#	Add commands below that you want to be executed at the beginning of a +#	"shorewall stop" command. +# +# See http://shorewall.net/shorewall_extension_scripts.htm for additional +# information. +# +############################################################################### +#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/stopped.footer b/puppet/modules/shorewall/files/boilerplate/stopped.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/stopped.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/stopped.header b/puppet/modules/shorewall/files/boilerplate/stopped.header new file mode 100644 index 00000000..438e5e05 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/stopped.header @@ -0,0 +1,13 @@ +# +# Shorewall version 4 - Stopped File +# +# /etc/shorewall/stopped +# +#	Add commands below that you want to be executed at the completion of a +#	"shorewall stop" command. +# +# See http://shorewall.net/shorewall_extension_scripts.htm for additional +# information. +# +############################################################################### +#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/tcclasses.footer b/puppet/modules/shorewall/files/boilerplate/tcclasses.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/tcclasses.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/tcclasses.header b/puppet/modules/shorewall/files/boilerplate/tcclasses.header new file mode 100644 index 00000000..025415ba --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/tcclasses.header @@ -0,0 +1,9 @@ +# +# Shorewall version 4 - Tcclasses File +# +# For information about entries in this file, type "man shorewall-tcclasses" +# +# See http://shorewall.net/traffic_shaping.htm for additional information. +# +############################################################################### +#INTERFACE:CLASS        MARK    RATE    CEIL    PRIORITY        OPTIONS diff --git a/puppet/modules/shorewall/files/boilerplate/tcdevices.footer b/puppet/modules/shorewall/files/boilerplate/tcdevices.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/tcdevices.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/tcdevices.header b/puppet/modules/shorewall/files/boilerplate/tcdevices.header new file mode 100644 index 00000000..fe7c3d1f --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/tcdevices.header @@ -0,0 +1,10 @@ +# +# Shorewall version 4 - Tcdevices File +# +# For information about entries in this file, type "man shorewall-tcdevices" +# +# See http://shorewall.net/traffic_shaping.htm for additional information. +# +############################################################################### +#NUMBER:        IN-BANDWITH     OUT-BANDWIDTH   OPTIONS         REDIRECTED +#INTERFACE                                                      INTERFACES diff --git a/puppet/modules/shorewall/files/boilerplate/tcrules.footer b/puppet/modules/shorewall/files/boilerplate/tcrules.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/tcrules.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/tcrules.header b/puppet/modules/shorewall/files/boilerplate/tcrules.header new file mode 100644 index 00000000..e0e7adcf --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/tcrules.header @@ -0,0 +1,15 @@ +# +# Shorewall version 4 - Tcrules File +# +# For information about entries in this file, type "man shorewall-tcrules" +# +# See http://shorewall.net/traffic_shaping.htm for additional information. +# For usage in selecting among multiple ISPs, see +# http://shorewall.net/MultiISP.html +# +# See http://shorewall.net/PacketMarking.html for a detailed description of +# the Netfilter/Shorewall packet marking mechanism. +###################################################################################################################### +#MARK   SOURCE          DEST            PROTO   DEST    SOURCE  USER    TEST    LENGTH  TOS   CONNBYTES         HELPER +#                                               PORT(S) PORT(S) + diff --git a/puppet/modules/shorewall/files/boilerplate/tunnel.footer b/puppet/modules/shorewall/files/boilerplate/tunnel.footer new file mode 100644 index 00000000..5e12d1da --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/tunnel.footer @@ -0,0 +1 @@ +#LAST LINE -- ADD YOUR ENTRIES BEFORE THIS ONE -- DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/tunnel.header b/puppet/modules/shorewall/files/boilerplate/tunnel.header new file mode 100644 index 00000000..638fd568 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/tunnel.header @@ -0,0 +1,11 @@ +# +# Shorewall version 4 - Tunnels File +# +# For information about entries in this file, type "man shorewall-tunnels" +# +# The manpage is also online at +# http://www.shorewall.net/manpages/shorewall-tunnels.html +# +############################################################################### +#TYPE			ZONE	GATEWAY		GATEWAY +#						ZONE diff --git a/puppet/modules/shorewall/files/boilerplate/zones.footer b/puppet/modules/shorewall/files/boilerplate/zones.footer new file mode 100644 index 00000000..662ac1cc --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/zones.footer @@ -0,0 +1 @@ +#LAST LINE - ADD YOUR ENTRIES ABOVE THIS ONE - DO NOT REMOVE diff --git a/puppet/modules/shorewall/files/boilerplate/zones.header b/puppet/modules/shorewall/files/boilerplate/zones.header new file mode 100644 index 00000000..8b82c2e5 --- /dev/null +++ b/puppet/modules/shorewall/files/boilerplate/zones.header @@ -0,0 +1,11 @@ +# +# Shorewall version 3.4 - Zones File +# +# For information about this file, type "man shorewall-zones" +# +# For more information, see http://www.shorewall.net/Documentation.htm#Zones +# +############################################################################### +#ZONE   TYPE            OPTIONS         IN                      OUT +#                                       OPTIONS                 OPTIONS +fw      firewall diff --git a/puppet/modules/shorewall/files/empty/.ignore b/puppet/modules/shorewall/files/empty/.ignore new file mode 100644 index 00000000..89cb1fe9 --- /dev/null +++ b/puppet/modules/shorewall/files/empty/.ignore @@ -0,0 +1 @@ +# file needed for git - don't remove it diff --git a/puppet/modules/shorewall/manifests/base.pp b/puppet/modules/shorewall/manifests/base.pp new file mode 100644 index 00000000..7959f018 --- /dev/null +++ b/puppet/modules/shorewall/manifests/base.pp @@ -0,0 +1,48 @@ +# base things for shorewall +class shorewall::base { + +  package { 'shorewall': +    ensure => $shorewall::ensure_version, +  } + +  # This file has to be managed in place, so shorewall can find it +  file { +    '/etc/shorewall/shorewall.conf': +      require => Package[shorewall], +      notify  => Service[shorewall], +      owner   => root, +      group   => 0, +      mode    => '0644'; +    '/etc/shorewall/puppet': +      ensure  => directory, +      require => Package[shorewall], +      owner   => root, +      group   => 0, +      mode    => '0644'; +  } + +  if $shorewall::conf_source { +    File['/etc/shorewall/shorewall.conf']{ +      source => $shorewall::conf_source, +    } +  } else { + +  Class['augeas'] -> Class['shorewall::base'] + +  augeas { 'shorewall_module_config_path': +    changes => 'set /files/etc/shorewall/shorewall.conf/CONFIG_PATH \'"/etc/shorewall/puppet:/etc/shorewall:/usr/share/shorewall"\'', +    lens    => 'Shellvars.lns', +    incl    => '/etc/shorewall/shorewall.conf', +    notify  => Service['shorewall'], +    require => Package['shorewall']; +  } +  } + +  service{'shorewall': +    ensure      => running, +    enable      => true, +    hasstatus   => true, +    hasrestart  => true, +    require     => Package['shorewall'], +  } +} diff --git a/puppet/modules/shorewall/manifests/blacklist.pp b/puppet/modules/shorewall/manifests/blacklist.pp new file mode 100644 index 00000000..afbe2165 --- /dev/null +++ b/puppet/modules/shorewall/manifests/blacklist.pp @@ -0,0 +1,9 @@ +define shorewall::blacklist( +    $proto = '-', +    $port = '-', +    $order='100' +){ +    shorewall::entry{"blacklist-${order}-${name}": +        line => "${name} ${proto} ${port}", +    }            +} diff --git a/puppet/modules/shorewall/manifests/centos.pp b/puppet/modules/shorewall/manifests/centos.pp new file mode 100644 index 00000000..f671bc9f --- /dev/null +++ b/puppet/modules/shorewall/manifests/centos.pp @@ -0,0 +1,13 @@ +# things needed on centos +class shorewall::centos inherits shorewall::base { +  if $::lsbmajdistrelease > 5 { +    augeas{'enable_shorewall': +      context => '/files/etc/sysconfig/shorewall', +      changes => 'set startup 1', +      lens    => 'Shellvars.lns', +      incl    => '/etc/sysconfig/shorewall', +      require => Package['shorewall'], +      notify  => Service['shorewall'], +    } +  } +} diff --git a/puppet/modules/shorewall/manifests/debian.pp b/puppet/modules/shorewall/manifests/debian.pp new file mode 100644 index 00000000..c7ed6077 --- /dev/null +++ b/puppet/modules/shorewall/manifests/debian.pp @@ -0,0 +1,11 @@ +class shorewall::debian inherits shorewall::base { +  file{'/etc/default/shorewall': +    content => template("shorewall/debian_default.erb"), +    require => Package['shorewall'], +    notify => Service['shorewall'], +    owner => root, group => 0, mode => 0644; +  } +  Service['shorewall']{ +    status => '/sbin/shorewall status' +  } +} diff --git a/puppet/modules/shorewall/manifests/entry.pp b/puppet/modules/shorewall/manifests/entry.pp new file mode 100644 index 00000000..c8fffc72 --- /dev/null +++ b/puppet/modules/shorewall/manifests/entry.pp @@ -0,0 +1,12 @@ +define shorewall::entry( +    $ensure = present, +    $line +){ +  $parts = split($name,'-') +  concat::fragment{$name: +    ensure => $ensure, +    content => "${line}\n", +    order => $parts[1], +    target => "/etc/shorewall/puppet/${parts[0]}", +  } +} diff --git a/puppet/modules/shorewall/manifests/extension_script.pp b/puppet/modules/shorewall/manifests/extension_script.pp new file mode 100644 index 00000000..569fcbf8 --- /dev/null +++ b/puppet/modules/shorewall/manifests/extension_script.pp @@ -0,0 +1,14 @@ +# See http://shorewall.net/shorewall_extension_scripts.htm +define shorewall::extension_script($script = '') { +    case $name { +        'init', 'initdone', 'start', 'started', 'stop', 'stopped', 'clear', 'refresh', 'continue', 'maclog': { +          file { "/etc/shorewall/puppet/${name}": +            content => "${script}\n", +            notify => Service[shorewall]; +          } +        } +        '', default: { +          err("${name}: unknown shorewall extension script") +        } +    } +} diff --git a/puppet/modules/shorewall/manifests/gentoo.pp b/puppet/modules/shorewall/manifests/gentoo.pp new file mode 100644 index 00000000..7b307a4e --- /dev/null +++ b/puppet/modules/shorewall/manifests/gentoo.pp @@ -0,0 +1,5 @@ +class shorewall::gentoo inherits shorewall::base { +    Package[shorewall]{ +        category => 'net-firewall', +    } +} diff --git a/puppet/modules/shorewall/manifests/host.pp b/puppet/modules/shorewall/manifests/host.pp new file mode 100644 index 00000000..f4002232 --- /dev/null +++ b/puppet/modules/shorewall/manifests/host.pp @@ -0,0 +1,10 @@ +define shorewall::host( +    $zone, +    $options = 'tcpflags,blacklist,norfc1918', +    $order='100' +){ +    shorewall::entry{"hosts-${order}-${name}": +        line => "${zone} ${name} ${options}" +    } +} + diff --git a/puppet/modules/shorewall/manifests/init.pp b/puppet/modules/shorewall/manifests/init.pp new file mode 100644 index 00000000..a5675646 --- /dev/null +++ b/puppet/modules/shorewall/manifests/init.pp @@ -0,0 +1,75 @@ +# Manage shorewall on your system +class shorewall( +  $startup                    = '1', +  $conf_source                = false, +  $ensure_version             = 'present', +  $tor_transparent_proxy_host = '127.0.0.1', +  $tor_transparent_proxy_port = '9040', +  $tor_user                   = $::operatingsystem ? { +    'Debian' => 'debian-tor', +    default  => 'tor' +  } +) { + +  case $::operatingsystem { +    gentoo: { include shorewall::gentoo } +    debian: { +      include shorewall::debian +      $dist_tor_user = 'debian-tor' +    } +    centos: { include shorewall::centos } +    ubuntu: { +    case $::lsbdistcodename { +      karmic: { include shorewall::ubuntu::karmic } +      default: { include shorewall::debian } +      } +    } +    default: { +      notice "unknown operatingsystem: ${::operatingsystem}" +      include shorewall::base +    } +  } + +  shorewall::managed_file{ +    [ +      # See http://www.shorewall.net/3.0/Documentation.htm#Zones +      'zones', +      # See http://www.shorewall.net/3.0/Documentation.htm#Interfaces +      'interfaces', +      # See http://www.shorewall.net/3.0/Documentation.htm#Hosts +      'hosts', +      # See http://www.shorewall.net/3.0/Documentation.htm#Policy +      'policy', +      # See http://www.shorewall.net/3.0/Documentation.htm#Rules +      'rules', +      # See http://www.shorewall.net/3.0/Documentation.htm#Masq +      'masq', +      # See http://www.shorewall.net/3.0/Documentation.htm#ProxyArp +      'proxyarp', +      # See http://www.shorewall.net/3.0/Documentation.htm#NAT +      'nat', +      # See http://www.shorewall.net/3.0/Documentation.htm#Blacklist +      'blacklist', +      # See http://www.shorewall.net/3.0/Documentation.htm#rfc1918 +      'rfc1918', +      # See http://www.shorewall.net/3.0/Documentation.htm#Routestopped +      'routestopped', +      # See http://www.shorewall.net/3.0/Documentation.htm#Variables +      'params', +      # See http://www.shorewall.net/3.0/traffic_shaping.htm +      'tcdevices', +      # See http://www.shorewall.net/3.0/traffic_shaping.htm +      'tcrules', +      # See http://www.shorewall.net/3.0/traffic_shaping.htm +      'tcclasses', +      # http://www.shorewall.net/manpages/shorewall-providers.html +      'providers', +      # See http://www.shorewall.net/manpages/shorewall-tunnels.html +      'tunnel', +      # See http://www.shorewall.net/MultiISP.html +      'rtrules', +      # See http://www.shorewall.net/manpages/shorewall-mangle.html +      'mangle', +    ]:; +  } +} diff --git a/puppet/modules/shorewall/manifests/interface.pp b/puppet/modules/shorewall/manifests/interface.pp new file mode 100644 index 00000000..403ee749 --- /dev/null +++ b/puppet/modules/shorewall/manifests/interface.pp @@ -0,0 +1,29 @@ +define shorewall::interface( +    $zone, +    $broadcast = 'detect', +    $options = 'tcpflags,blacklist,routefilter,nosmurfs,logmartians', +    $add_options = '', +    $rfc1918 = false, +    $dhcp = false, +    $order = 100 +){ +    $added_opts = $add_options ? { +        ''      => '', +        default => ",${add_options}", +    } + +    $dhcp_opt = $dhcp ? { +        false   => '', +        default => ',dhcp', +    } + +    $rfc1918_opt = $rfc1918 ? { +        false   => ',norfc1918', +        default => '', +    } + +    shorewall::entry { "interfaces-${order}-${name}": +        line => "${zone} ${name} ${broadcast} ${options}${dhcp_opt}${rfc1918_opt}${added_opts}", +    } +} + diff --git a/puppet/modules/shorewall/manifests/managed_file.pp b/puppet/modules/shorewall/manifests/managed_file.pp new file mode 100644 index 00000000..d564daa7 --- /dev/null +++ b/puppet/modules/shorewall/manifests/managed_file.pp @@ -0,0 +1,17 @@ +define shorewall::managed_file () { +  concat{ "/etc/shorewall/puppet/${name}": +    notify => Service['shorewall'], +    require => File['/etc/shorewall/puppet'], +    owner => root, group => 0, mode => 0600; +  } +  concat::fragment { +    "${name}-header": +      source => "puppet:///modules/shorewall/boilerplate/${name}.header", +      target => "/etc/shorewall/puppet/${name}", +      order => '000'; +    "${name}-footer": +      source => "puppet:///modules/shorewall/boilerplate/${name}.footer", +      target => "/etc/shorewall/puppet/${name}", +      order => '999'; +  } +} diff --git a/puppet/modules/shorewall/manifests/mangle.pp b/puppet/modules/shorewall/manifests/mangle.pp new file mode 100644 index 00000000..e3fd1b3b --- /dev/null +++ b/puppet/modules/shorewall/manifests/mangle.pp @@ -0,0 +1,19 @@ +define shorewall::mangle( +  $source, +  $destination, +  $proto           = '-', +  $destinationport = '-', +  $sourceport      = '-', +  $user            = '-', +  $test            = '-', +  $length          = '-', +  $tos             = '-', +  $connbytes       = '-', +  $helper          = '-', +  $headers         = '-', +  $order           = '100' +){ +  shorewall::entry{"mangle-${order}-${name}": +    line => "${name} ${source} ${destination} ${proto} ${destinationport} ${sourceport} ${user} ${test} ${length} ${tos} ${connbytes} ${helper} ${headers}" +  } +} diff --git a/puppet/modules/shorewall/manifests/masq.pp b/puppet/modules/shorewall/manifests/masq.pp new file mode 100644 index 00000000..fb097e5e --- /dev/null +++ b/puppet/modules/shorewall/manifests/masq.pp @@ -0,0 +1,17 @@ +# mark is new in 3.4.4 +# source (= subnet) = Set of hosts that you wish to masquerade. +# address = If  you  specify  an  address here, SNAT will be used and this will be the source address. +define shorewall::masq( +    $interface, +    $source, $address = '-', +    $proto = '-', +    $port = '-', +    $ipsec = '-', +    $mark = '', +    $order='100' +){ +    shorewall::entry{"masq-${order}-${name}": +        line => "# ${name}\n${interface} ${source} ${address} ${proto} ${port} ${ipsec} ${mark}" +    } +} + diff --git a/puppet/modules/shorewall/manifests/nat.pp b/puppet/modules/shorewall/manifests/nat.pp new file mode 100644 index 00000000..e29b7849 --- /dev/null +++ b/puppet/modules/shorewall/manifests/nat.pp @@ -0,0 +1,11 @@ +define shorewall::nat( +    $interface, +    $internal, +    $all = 'no', +    $local = 'yes', +    $order='100' +){ +    shorewall::entry{"nat-${order}-${name}": +        line => "${name} ${interface} ${internal} ${all} ${local}" +    }            +} diff --git a/puppet/modules/shorewall/manifests/params.pp b/puppet/modules/shorewall/manifests/params.pp new file mode 100644 index 00000000..3bc56630 --- /dev/null +++ b/puppet/modules/shorewall/manifests/params.pp @@ -0,0 +1,5 @@ +define shorewall::params($value, $order='100'){ +    shorewall::entry{"params-${order}-${name}": +        line => "${name}=${value}", +    } +} diff --git a/puppet/modules/shorewall/manifests/policy.pp b/puppet/modules/shorewall/manifests/policy.pp new file mode 100644 index 00000000..efee05b5 --- /dev/null +++ b/puppet/modules/shorewall/manifests/policy.pp @@ -0,0 +1,12 @@ +define shorewall::policy( +    $sourcezone, +    $destinationzone, +    $policy, $shloglevel = '-', +    $limitburst = '-', +    $order +){ +    shorewall::entry{"policy-${order}-${name}": +        line => "# ${name}\n${sourcezone} ${destinationzone} ${policy} ${shloglevel} ${limitburst}", +    } +} + diff --git a/puppet/modules/shorewall/manifests/providers.pp b/puppet/modules/shorewall/manifests/providers.pp new file mode 100644 index 00000000..a1f8726a --- /dev/null +++ b/puppet/modules/shorewall/manifests/providers.pp @@ -0,0 +1,16 @@ +# manage providers +define shorewall::providers( +  $provider   = $name, +  $number     = '', +  $mark       = '', +  $duplicate  = 'main', +  $interface  = '', +  $gateway    = '', +  $options    = '', +  $copy       = '', +  $order      = '100' +){ +  shorewall::entry{"providers-${order}-${name}": +    line => "# ${name}\n${provider} ${number} ${mark} ${duplicate} ${interface} ${gateway} ${options} ${copy}" +  } +} diff --git a/puppet/modules/shorewall/manifests/proxyarp.pp b/puppet/modules/shorewall/manifests/proxyarp.pp new file mode 100644 index 00000000..1af554fb --- /dev/null +++ b/puppet/modules/shorewall/manifests/proxyarp.pp @@ -0,0 +1,11 @@ +define shorewall::proxyarp( +    $interface, +    $external, +    $haveroute = yes, +    $persistent = no, +    $order='100' +    ){ +    shorewall::entry{"proxyarp-${order}-${name}": +        line => "# ${name}\n${name} ${interface} ${external} ${haveroute} ${persistent}" +    } +} diff --git a/puppet/modules/shorewall/manifests/rfc1918.pp b/puppet/modules/shorewall/manifests/rfc1918.pp new file mode 100644 index 00000000..31dce5dc --- /dev/null +++ b/puppet/modules/shorewall/manifests/rfc1918.pp @@ -0,0 +1,8 @@ +define shorewall::rfc1918( +    $action = 'logdrop', +    $order='100' +){ +    shorewall::entry{"rfc1918-${order}-${name}": +        line => "${name} ${action}" +    }    +} diff --git a/puppet/modules/shorewall/manifests/routestopped.pp b/puppet/modules/shorewall/manifests/routestopped.pp new file mode 100644 index 00000000..aca57b51 --- /dev/null +++ b/puppet/modules/shorewall/manifests/routestopped.pp @@ -0,0 +1,14 @@ +define shorewall::routestopped( +    $interface = $name, +    $host = '-', +    $options = '', +    $order='100' +){ +    $real_interface = $interface ? {  +        '' => $name, +        default => $interface, +    }    +    shorewall::entry{"routestopped-${order}-${name}": +        line => "${real_interface} ${host} ${options}", +    }            +} diff --git a/puppet/modules/shorewall/manifests/rtrules.pp b/puppet/modules/shorewall/manifests/rtrules.pp new file mode 100644 index 00000000..3810f26d --- /dev/null +++ b/puppet/modules/shorewall/manifests/rtrules.pp @@ -0,0 +1,11 @@ +define shorewall::rtrules( +    $source = '-', +    $destination = '-', +    $provider, +    $priority = '10000', +    $mark, +){ +    shorewall::entry { "rtrules-${mark}-${name}": +        line => "# ${name}\n${source} ${destination} ${provider} ${priority} ${mark}", +    } +} diff --git a/puppet/modules/shorewall/manifests/rule.pp b/puppet/modules/shorewall/manifests/rule.pp new file mode 100644 index 00000000..2fe91e27 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rule.pp @@ -0,0 +1,20 @@ +# mark is new in 3.4.4 +define shorewall::rule( +    $ensure = present, +    $action, +    $source, +    $destination, +    $proto = '-', +    $destinationport = '-', +    $sourceport = '-', +    $originaldest = '-', +    $ratelimit = '-', +    $user = '-', +    $mark = '', +    $order +){ +  shorewall::entry{"rules-${order}-${name}": +    ensure => $ensure, +    line => "# ${name}\n${action} ${source} ${destination} ${proto} ${destinationport} ${sourceport} ${originaldest} ${ratelimit} ${user} ${mark}", +  } +} diff --git a/puppet/modules/shorewall/manifests/rule_section.pp b/puppet/modules/shorewall/manifests/rule_section.pp new file mode 100644 index 00000000..82984ca2 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rule_section.pp @@ -0,0 +1,7 @@ +define shorewall::rule_section( +    $order +){ +    shorewall::entry{"rules-${order}-${name}": +        line => "SECTION ${name}", +    }        +} diff --git a/puppet/modules/shorewall/manifests/rules/cobbler.pp b/puppet/modules/shorewall/manifests/rules/cobbler.pp new file mode 100644 index 00000000..e04e4925 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/cobbler.pp @@ -0,0 +1,19 @@ +class shorewall::rules::cobbler { +     shorewall::rule{'net-me-syslog-xmlrpc-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '25150:25151', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule{'net-me-syslog-xmlrpc-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '25150:25151', +        order           => 240, +        action          => 'ACCEPT'; +    } +    include shorewall::rules::rsync +} diff --git a/puppet/modules/shorewall/manifests/rules/dns.pp b/puppet/modules/shorewall/manifests/rules/dns.pp new file mode 100644 index 00000000..99311cae --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/dns.pp @@ -0,0 +1,18 @@ +class shorewall::rules::dns { +    shorewall::rule { +        'net-me-tcp_dns': +                        source          =>      'net', +                        destination     =>      '$FW', +                        proto           =>      'tcp', +                        destinationport =>      '53', +                        order           =>      240, +                        action          =>      'ACCEPT'; +        'net-me-udp_dns': +                        source          =>      'net', +                        destination     =>      '$FW', +                        proto           =>      'udp', +                        destinationport =>      '53', +                        order           =>      240, +                        action          =>      'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/dns/disable.pp b/puppet/modules/shorewall/manifests/rules/dns/disable.pp new file mode 100644 index 00000000..36541da4 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/dns/disable.pp @@ -0,0 +1,5 @@ +class shorewall::rules::dns::disable inherits shorewall::rules::dns { +  Shorewall::Rule['net-me-tcp_dns', 'net-me-udp_dns']{ +        action  => 'DROP', +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/ekeyd.pp b/puppet/modules/shorewall/manifests/rules/ekeyd.pp new file mode 100644 index 00000000..dbff02fe --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/ekeyd.pp @@ -0,0 +1,10 @@ +class shorewall::rules::ekeyd { +  shorewall::rule { 'net-me-tcp_ekeyd': +    source          => 'net', +    destination     => '$FW', +    proto           => 'tcp', +    destinationport => '8888', +    order           => 240, +    action          => 'ACCEPT'; +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/ftp.pp b/puppet/modules/shorewall/manifests/rules/ftp.pp new file mode 100644 index 00000000..6d34c78f --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/ftp.pp @@ -0,0 +1,10 @@ +class shorewall::rules::ftp { +    shorewall::rule { 'net-me-ftp-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '21', +        order           => 240, +        action          => 'FTP/ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/gitdaemon.pp b/puppet/modules/shorewall/manifests/rules/gitdaemon.pp new file mode 100644 index 00000000..21372f63 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/gitdaemon.pp @@ -0,0 +1,10 @@ +class shorewall::rules::gitdaemon { +        shorewall::rule {'net-me-tcp_gitdaemon': +            source          => 'net', +            destination     => '$FW', +            proto           => 'tcp', +            destinationport => '9418', +            order           => 240, +            action          => 'ACCEPT'; +        } +} diff --git a/puppet/modules/shorewall/manifests/rules/gitdaemon/absent.pp b/puppet/modules/shorewall/manifests/rules/gitdaemon/absent.pp new file mode 100644 index 00000000..ade6fba0 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/gitdaemon/absent.pp @@ -0,0 +1,5 @@ +class shorewall::rules::gitdaemon::absent inherits shorewall::rules::gitdaemon { +  Shorewall::Rule['net-me-tcp_gitdaemon']{ +    ensure => absent, +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/http.pp b/puppet/modules/shorewall/manifests/rules/http.pp new file mode 100644 index 00000000..e6a9bdef --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/http.pp @@ -0,0 +1,10 @@ +class shorewall::rules::http { +    shorewall::rule { 'net-me-http-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '80', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/http/disable.pp b/puppet/modules/shorewall/manifests/rules/http/disable.pp new file mode 100644 index 00000000..5d9170ca --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/http/disable.pp @@ -0,0 +1,5 @@ +class shorewall::rules::http::disable inherits shorewall::rules::http { +  Shorewall::Rule['net-me-http-tcp']{ +        action  => 'DROP', +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/https.pp b/puppet/modules/shorewall/manifests/rules/https.pp new file mode 100644 index 00000000..cc49d100 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/https.pp @@ -0,0 +1,10 @@ +class shorewall::rules::https { +    shorewall::rule { 'net-me-https-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '443', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/identd.pp b/puppet/modules/shorewall/manifests/rules/identd.pp new file mode 100644 index 00000000..719e581c --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/identd.pp @@ -0,0 +1,10 @@ +class shorewall::rules::identd { +  shorewall::rule { 'net-me-identd-tcp': +    source          => 'net', +    destination     => '$FW', +    proto           => 'tcp', +    destinationport => '113', +    order           => 240, +    action          => 'ACCEPT'; +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/imap.pp b/puppet/modules/shorewall/manifests/rules/imap.pp new file mode 100644 index 00000000..7fbe1818 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/imap.pp @@ -0,0 +1,11 @@ +class shorewall::rules::imap { +    shorewall::rule { +        'net-me-tcp_imap_s': +            source          =>      'net', +            destination     =>      '$FW', +            proto           =>      'tcp', +            destinationport =>      '143,993', +            order           =>      260, +            action          =>      'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/ipsec.pp b/puppet/modules/shorewall/manifests/rules/ipsec.pp new file mode 100644 index 00000000..82adff09 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/ipsec.pp @@ -0,0 +1,32 @@ +class shorewall::rules::ipsec( +  $source = 'net' +) { +    shorewall::rule { +      'net-me-ipsec-udp': +        source          => $shorewall::rules::ipsec::source, +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '500', +        order           => 240, +        action          => 'ACCEPT'; +      'me-net-ipsec-udp': +        source          => '$FW', +        destination     => $shorewall::rules::ipsec::source, +        proto           => 'udp', +        destinationport => '500', +        order           => 240, +        action          => 'ACCEPT'; +      'net-me-ipsec': +        source          => $shorewall::rules::ipsec::source, +        destination     => '$FW', +        proto           => 'esp', +        order           => 240, +        action          => 'ACCEPT'; +      'me-net-ipsec': +        source          => '$FW', +        destination     => $shorewall::rules::ipsec::source, +        proto           => 'esp', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/ipsec_nat.pp b/puppet/modules/shorewall/manifests/rules/ipsec_nat.pp new file mode 100644 index 00000000..6c0d5072 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/ipsec_nat.pp @@ -0,0 +1,18 @@ +class shorewall::rules::ipsec_nat { +    shorewall::rule { +      'net-me-ipsec-nat-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '4500', +        order           => 240, +        action          => 'ACCEPT'; +      'me-net-ipsec-nat-udp': +        source          => '$FW', +        destination     => 'net', +        proto           => 'udp', +        destinationport => '4500', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/jabberserver.pp b/puppet/modules/shorewall/manifests/rules/jabberserver.pp new file mode 100644 index 00000000..3b38b294 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/jabberserver.pp @@ -0,0 +1,19 @@ +class shorewall::rules::jabberserver { +  shorewall::rule { +    'net-me-tcp_jabber': +            source          => 'net', +            destination     => '$FW', +            proto           => 'tcp', +            destinationport => '5222,5223,5269', +            order           => 240, +            action          => 'ACCEPT'; +    'me-net-tcp_jabber_s2s': +            source          => '$FW', +            destination     => 'net', +            proto           => 'tcp', +            destinationport => '5260,5269,5270,5271,5272', +            order           => 240, +            action          => 'ACCEPT'; +  } + +} diff --git a/puppet/modules/shorewall/manifests/rules/jetty.pp b/puppet/modules/shorewall/manifests/rules/jetty.pp new file mode 100644 index 00000000..4080e7e6 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/jetty.pp @@ -0,0 +1,12 @@ +class shorewall::rules::jetty { +    # open jetty port +    shorewall::rule { +        'net-me-jetty-tcp': +            source          => 'net', +            destination     => '$FW', +            proto           => 'tcp', +            destinationport => '8080', +            order           => 240, +            action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/jetty/http.pp b/puppet/modules/shorewall/manifests/rules/jetty/http.pp new file mode 100644 index 00000000..4c0652be --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/jetty/http.pp @@ -0,0 +1,9 @@ +class shorewall::rules::jetty::http { +    # dnat +    shorewall::rule { +        'dnat-http-to-jetty': +            destination     =>      "net:${::ipaddress}:8080", +            destinationport =>      '80', +            source          =>      'net', proto => 'tcp', order => 140, action => 'DNAT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/jetty/ssl.pp b/puppet/modules/shorewall/manifests/rules/jetty/ssl.pp new file mode 100644 index 00000000..f7517493 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/jetty/ssl.pp @@ -0,0 +1,11 @@ +class shorewall::rules::jetty::ssl { +    shorewall::rule { +        'net-me-jettyssl-tcp': +            source          => 'net', +            destination     => '$FW', +            proto           => 'tcp', +            destinationport => '8443', +            order           => 240, +            action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/keyserver.pp b/puppet/modules/shorewall/manifests/rules/keyserver.pp new file mode 100644 index 00000000..2ade9c1e --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/keyserver.pp @@ -0,0 +1,11 @@ +class shorewall::rules::keyserver { +	shorewall::rule { +		'net-me-tcp_keyserver': +      source      => 'net', +  		destination     => '$FW', +	  	proto           => 'tcp', +		  destinationport => '11371,11372', +   		order           => 240, +	    action          => 'ACCEPT'; +	} +} diff --git a/puppet/modules/shorewall/manifests/rules/libvirt/host.pp b/puppet/modules/shorewall/manifests/rules/libvirt/host.pp new file mode 100644 index 00000000..c2268659 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/libvirt/host.pp @@ -0,0 +1,79 @@ +class shorewall::rules::libvirt::host ( +  $vmz           = 'vmz', +  $masq_iface    = 'eth0', +  $debproxy_port = 8000, +  $accept_dhcp   = true, +  $vmz_iface     = 'virbr0', +  ) { + +  define shorewall::rule::accept::from_vmz ( +    $proto           = '-', +    $destinationport = '-', +    $action          = 'ACCEPT' +    ) { +      shorewall::rule { $name: +        source          => $shorewall::rules::libvirt::host::vmz, +        destination     => '$FW', +        order           => 300, +        proto           => $proto, +        destinationport => $destinationport, +        action          => $action; +      } +    } + +  shorewall::policy { +    'fw-to-vmz': +      sourcezone              =>      '$FW', +      destinationzone         =>      $vmz, +      policy                  =>      'ACCEPT', +      order                   =>      110; +    'vmz-to-net': +      sourcezone              =>      $vmz, +      destinationzone         =>      'net', +      policy                  =>      'ACCEPT', +      order                   =>      200; +    'vmz-to-all': +      sourcezone              =>      $vmz, +      destinationzone         =>      'all', +      policy                  =>      'DROP', +      shloglevel              =>      'info', +      order                   =>      800; +  } + +  shorewall::rule::accept::from_vmz { +    'accept_dns_from_vmz': +      action          => 'DNS(ACCEPT)'; +    'accept_tftp_from_vmz': +      action          => 'TFTP(ACCEPT)'; +    'accept_puppet_from_vmz': +      proto           => 'tcp', +      destinationport => '8140', +      action          => 'ACCEPT'; +  } + +  if $accept_dhcp { +    shorewall::mangle { 'CHECKSUM:T': +      source          => '-', +      destination     => $vmz_iface, +      proto           => 'udp', +      destinationport => '68'; +    } +  } + +  if $debproxy_port { +    shorewall::rule::accept::from_vmz { 'accept_debproxy_from_vmz': +      proto           => 'tcp', +      destinationport => $debproxy_port, +      action          => 'ACCEPT'; +    } +  } + +  if $masq_iface { +    shorewall::masq { +      "masq-${masq_iface}": +        interface => $masq_iface, +        source    => '10.0.0.0/8,169.254.0.0/16,172.16.0.0/12,192.168.0.0/16'; +    } +  } + +} diff --git a/puppet/modules/shorewall/manifests/rules/managesieve.pp b/puppet/modules/shorewall/manifests/rules/managesieve.pp new file mode 100644 index 00000000..63fafcb6 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/managesieve.pp @@ -0,0 +1,11 @@ +class shorewall::rules::managesieve { +    shorewall::rule { +        'net-me-tcp_managesieve': +            source          =>      'net', +            destination     =>      '$FW', +            proto           =>      'tcp', +            destinationport =>      '2000', +            order           =>      260, +            action          =>      'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/mdns.pp b/puppet/modules/shorewall/manifests/rules/mdns.pp new file mode 100644 index 00000000..76b1fd90 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/mdns.pp @@ -0,0 +1,8 @@ +class shorewall::rules::mdns { +    shorewall::rule { 'net-me-mdns': +        source          => 'net', +        destination     => '$FW', +        order           => 240, +        action          => 'mDNS(ACCEPT)'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/munin.pp b/puppet/modules/shorewall/manifests/rules/munin.pp new file mode 100644 index 00000000..a20a4e0a --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/munin.pp @@ -0,0 +1,16 @@ +class shorewall::rules::munin( +  $munin_port = '4949', +  $munin_collector = ['127.0.0.1'], +  $collector_source = 'net' +){ +    shorewall::params { 'MUNINPORT': value => $munin_port } +    shorewall::params { 'MUNINCOLLECTOR': value => join(any2array($munin_collector),',') } +    shorewall::rule{'net-me-munin-tcp': +        source          => "${collector_source}:\$MUNINCOLLECTOR", +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '$MUNINPORT', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/mysql.pp b/puppet/modules/shorewall/manifests/rules/mysql.pp new file mode 100644 index 00000000..0da68a19 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/mysql.pp @@ -0,0 +1,11 @@ +class shorewall::rules::mysql { +	shorewall::rule { +		'net-me-tcp_mysql': +            source          => 'net', +            destination     => '$FW', +            proto           => 'tcp', +            destinationport => '3306', +            order           => 240, +            action          => 'ACCEPT'; +	} +} diff --git a/puppet/modules/shorewall/manifests/rules/nfsd.pp b/puppet/modules/shorewall/manifests/rules/nfsd.pp new file mode 100644 index 00000000..bd509cf2 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/nfsd.pp @@ -0,0 +1,115 @@ +class shorewall::rules::nfsd { +    shorewall::rule { 'net-me-portmap-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '111', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-portmap-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '111', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-rpc.statd-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '662', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-rpc.statd-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '662', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'me-net-rpc.statd-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '2020', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'me-net-rpc.statd-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '2020', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-rpc.lockd-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '32803', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-rpc.lockd-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '32769', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-rpc.mountd-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '892', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-rpc.mountd-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '892', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-rpc.rquotad-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '875', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-rpc.rquoata-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '875', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-rpc.nfsd-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '2049', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-rpc.nfsd-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '2049', +        order           => 240, +        action          => 'ACCEPT'; +    } + +} diff --git a/puppet/modules/shorewall/manifests/rules/ntp/client.pp b/puppet/modules/shorewall/manifests/rules/ntp/client.pp new file mode 100644 index 00000000..e0db8d45 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/ntp/client.pp @@ -0,0 +1,11 @@ +class shorewall::rules::ntp::client { +    # open ntp udp port to fetch time +    shorewall::rule {'me-net-udp_ntp': +        source          => '$FW', +        destination     => 'net', +        proto           => 'udp', +        destinationport => '123', +        order           => 251, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/ntp/server.pp b/puppet/modules/shorewall/manifests/rules/ntp/server.pp new file mode 100644 index 00000000..ed0968db --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/ntp/server.pp @@ -0,0 +1,10 @@ +class shorewall::rules::ntp::server { +    shorewall::rule {'net-me-udp_ntp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '123', +        order           => 241,  +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/openfire.pp b/puppet/modules/shorewall/manifests/rules/openfire.pp new file mode 100644 index 00000000..0e6d1d80 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/openfire.pp @@ -0,0 +1,12 @@ +class shorewall::rules::openfire { +  include shorewall::rules::jaberserver + +  shorewall::rule { 'me-all-openfire-tcp': +    source          => '$FW', +    destination     => 'all', +    proto           => 'tcp', +    destinationport => '7070,7443,7777', +    order           => 240, +    action          => 'ACCEPT'; +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/ekeyd.pp b/puppet/modules/shorewall/manifests/rules/out/ekeyd.pp new file mode 100644 index 00000000..8acdaad5 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/ekeyd.pp @@ -0,0 +1,10 @@ +define shorewall::rules::out::ekeyd($host) { +  shorewall::rule { "me-${name}-tcp_ekeyd": +    source          => '$FW', +    destination     => "${name}:${host}", +    proto           => 'tcp', +    destinationport => '8888', +    order           => 240, +    action          => 'ACCEPT'; +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/git.pp b/puppet/modules/shorewall/manifests/rules/out/git.pp new file mode 100644 index 00000000..cb88da85 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/git.pp @@ -0,0 +1,10 @@ +class shorewall::rules::out::git { +    shorewall::rule{'me-net-git-tcp': +        source          => '$FW', +        destination     => 'net', +        proto           => 'tcp', +        destinationport => '9418', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/ibackup.pp b/puppet/modules/shorewall/manifests/rules/out/ibackup.pp new file mode 100644 index 00000000..856bcdb9 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/ibackup.pp @@ -0,0 +1,12 @@ +class shorewall::rules::out::ibackup( +  $backup_host +){ +  shorewall::rule { 'me-net-tcp_backupssh': +    source          => '$FW', +    destination     => "net:${backup_host}", +    proto           => 'tcp', +    destinationport => 'ssh', +    order           => 240, +    action          => 'ACCEPT'; +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/imap.pp b/puppet/modules/shorewall/manifests/rules/out/imap.pp new file mode 100644 index 00000000..f1313d2c --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/imap.pp @@ -0,0 +1,11 @@ +class shorewall::rules::out::imap { +    shorewall::rule { +        'me-net-tcp_imap_s': +            source          =>      '$FW', +            destination     =>      'net', +            proto           =>      'tcp', +            destinationport =>      '143,993', +            order           =>      260, +            action          =>      'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/irc.pp b/puppet/modules/shorewall/manifests/rules/out/irc.pp new file mode 100644 index 00000000..9c8590ab --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/irc.pp @@ -0,0 +1,10 @@ +class shorewall::rules::out::irc { +    shorewall::rule{'me-net-irc-tcp': +        source          => '$FW', +        destination     => 'net', +        proto           => 'tcp', +        destinationport => '6667', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/ircs.pp b/puppet/modules/shorewall/manifests/rules/out/ircs.pp new file mode 100644 index 00000000..a71585d8 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/ircs.pp @@ -0,0 +1,10 @@ +class shorewall::rules::out::ircs { +    shorewall::rule{'me-net-ircs-tcp': +        source          => '$FW', +        destination     => 'net', +        proto           => 'tcp', +        destinationport => '6669', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/keyserver.pp b/puppet/modules/shorewall/manifests/rules/out/keyserver.pp new file mode 100644 index 00000000..aa7147e0 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/keyserver.pp @@ -0,0 +1,11 @@ +class shorewall::rules::out::keyserver { +  shorewall::rule { +    'me-net-tcp_keyserver': +      source          =>  '$FW', +      destination     =>  'net', +      proto           =>  'tcp', +      destinationport =>  '11371,11372', +      order           =>  240, +      action          => 'ACCEPT';  + } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/managesieve.pp b/puppet/modules/shorewall/manifests/rules/out/managesieve.pp new file mode 100644 index 00000000..b0e1c3da --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/managesieve.pp @@ -0,0 +1,11 @@ +class shorewall::rules::out::managesieve { +    shorewall::rule { +        'me-net-tcp_managesieve': +            source          =>      '$FW', +            destination     =>      'net', +            proto           =>      'tcp', +            destinationport =>      '2000', +            order           =>      260, +            action          =>      'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/munin.pp b/puppet/modules/shorewall/manifests/rules/out/munin.pp new file mode 100644 index 00000000..004a3d5b --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/munin.pp @@ -0,0 +1,10 @@ +class shorewall::rules::out::munin { +  shorewall::rule { 'me-net-rcp_muninhost': +    source          => '$FW', +    destination     => 'net', +    proto           => 'tcp', +    destinationport => '4949', +    order           => 340, +    action          => 'ACCEPT'; +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/mysql.pp b/puppet/modules/shorewall/manifests/rules/out/mysql.pp new file mode 100644 index 00000000..1334ba6a --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/mysql.pp @@ -0,0 +1,11 @@ +class shorewall::rules::out::mysql { +    shorewall::rule { +        'me-net-tcp_mysql': +            source          =>  '$FW', +            destination     =>  'net', +            proto           =>  'tcp', +            destinationport =>  '3306', +            order           =>  240, +            action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/pop3.pp b/puppet/modules/shorewall/manifests/rules/out/pop3.pp new file mode 100644 index 00000000..ebd4828f --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/pop3.pp @@ -0,0 +1,11 @@ +class shorewall::rules::out::pop3 { +    shorewall::rule { +        'me-net-tcp_pop3_s': +            source          =>      '$FW', +            destination     =>      'net', +            proto           =>      'tcp', +            destinationport =>      'pop3,pop3s', +            order           =>      260, +            action          =>      'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/postgres.pp b/puppet/modules/shorewall/manifests/rules/out/postgres.pp new file mode 100644 index 00000000..a62d75d7 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/postgres.pp @@ -0,0 +1,11 @@ +class shorewall::rules::out::postgres { +    shorewall::rule { +        'me-net-tcp_postgres': +            source          =>  '$FW', +            destination     =>  'net', +            proto           =>  'tcp', +            destinationport =>  '5432', +            order           =>  240, +            action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/puppet.pp b/puppet/modules/shorewall/manifests/rules/out/puppet.pp new file mode 100644 index 00000000..cbe8cce7 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/puppet.pp @@ -0,0 +1,20 @@ +class shorewall::rules::out::puppet( +  $puppetserver = "puppet.${::domain}", +  $puppetserver_port = 8140, +  $puppetserver_signport = 8141 +) { +  class{'shorewall::rules::puppet': +    puppetserver          => $puppetserver, +    puppetserver_port     => $puppetserver_port, +    puppetserver_signport => $puppetserver_signport, +  } +  # we want to connect to the puppet server +  shorewall::rule { 'me-net-puppet_tcp': +    source          =>      '$FW', +    destination     =>      'net:$PUPPETSERVER', +    proto           =>      'tcp', +    destinationport =>      '$PUPPETSERVER_PORT,$PUPPETSERVER_SIGN_PORT', +    order           =>      340, +    action          =>      'ACCEPT'; +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/silc.pp b/puppet/modules/shorewall/manifests/rules/out/silc.pp new file mode 100644 index 00000000..830df9c3 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/silc.pp @@ -0,0 +1,19 @@ +class shorewall::rules::out::silc { +  shorewall::rule{ +    'me-net-silc-tcp': +      source          => '$FW', +      destination     => 'net', +      proto           => 'tcp', +      destinationport => '706', +      order           => 240, +      action          => 'ACCEPT'; +    'me-net-silc-udp': +      source          => '$FW', +      destination     => 'net', +      proto           => 'udp', +      destinationport => '706', +      order           => 240, +      action          => 'ACCEPT'; + +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/smtp.pp b/puppet/modules/shorewall/manifests/rules/out/smtp.pp new file mode 100644 index 00000000..2cc77cc3 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/smtp.pp @@ -0,0 +1,11 @@ +class shorewall::rules::out::smtp { +    shorewall::rule { +        'me-net-tcp_smtp': +            source          =>  '$FW', +            destination     =>  'net', +            proto           =>  'tcp', +            destinationport =>  'smtp', +            order           =>  240, +            action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/ssh.pp b/puppet/modules/shorewall/manifests/rules/out/ssh.pp new file mode 100644 index 00000000..c18e299b --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/ssh.pp @@ -0,0 +1,10 @@ +class shorewall::rules::out::ssh { +    shorewall::rule { 'me-net-tcp_ssh': +        source          => '$FW', +        destination     => 'net', +        proto           => 'tcp', +        destinationport => 'ssh', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/ssh/disable.pp b/puppet/modules/shorewall/manifests/rules/out/ssh/disable.pp new file mode 100644 index 00000000..223bf73b --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/ssh/disable.pp @@ -0,0 +1,5 @@ +class shorewall::rules::out::ssh::disable inherits shorewall::rules::out::ssh { +  Shorewall::Rule['me-net-tcp_ssh']{ +    action => 'DROP', +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/ssh/remove.pp b/puppet/modules/shorewall/manifests/rules/out/ssh/remove.pp new file mode 100644 index 00000000..bc0acf37 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/ssh/remove.pp @@ -0,0 +1,5 @@ +class shorewall::rules::out::ssh::remove inherits shorewall::rules::out::ssh { +  Shorewall::Rule['me-net-tcp_ssh']{ +    ensure => absent, +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/whois.pp b/puppet/modules/shorewall/manifests/rules/out/whois.pp new file mode 100644 index 00000000..d003d5c1 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/whois.pp @@ -0,0 +1,11 @@ +class shorewall::rules::out::whois { +    # open whois tcp port  +    shorewall::rule {'me-net-tcp_whois': +        source          => '$FW', +        destination     => 'net', +        proto           => 'tcp', +        destinationport => '43', +        order           => 251, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/out/xmpp.pp b/puppet/modules/shorewall/manifests/rules/out/xmpp.pp new file mode 100644 index 00000000..a1b4577c --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/out/xmpp.pp @@ -0,0 +1,10 @@ +class shorewall::rules::out::xmpp { +    shorewall::rule{'me-net-xmpp-tcp': +        source          => '$FW', +        destination     => 'net', +        proto           => 'tcp', +        destinationport => '5222', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/pop3.pp b/puppet/modules/shorewall/manifests/rules/pop3.pp new file mode 100644 index 00000000..25878568 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/pop3.pp @@ -0,0 +1,11 @@ +class shorewall::rules::pop3 { +    shorewall::rule { +        'net-me-tcp_pop3_s': +            source          =>      'net', +            destination     =>      '$FW', +            proto           =>      'tcp', +            destinationport =>      'pop3,pop3s', +            order           =>      260, +            action          =>      'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/postgres.pp b/puppet/modules/shorewall/manifests/rules/postgres.pp new file mode 100644 index 00000000..1a22027e --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/postgres.pp @@ -0,0 +1,10 @@ +class shorewall::rules::postgres { +    shorewall::rule { 'net-me-tcp_postgres': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '5432', +        order           => 250, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/puppet.pp b/puppet/modules/shorewall/manifests/rules/puppet.pp new file mode 100644 index 00000000..84e7d813 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/puppet.pp @@ -0,0 +1,11 @@ +class shorewall::rules::puppet( +  $puppetserver = "puppet.${::domain}", +  $puppetserver_port = 8140, +  $puppetserver_signport = 8141 +){ +  shorewall::params{ +    'PUPPETSERVER':             value => $puppetserver; +    'PUPPETSERVER_PORT':        value => $puppetserver_port; +    'PUPPETSERVER_SIGN_PORT':   value => $puppetserver_signport; +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/puppet/master.pp b/puppet/modules/shorewall/manifests/rules/puppet/master.pp new file mode 100644 index 00000000..925979c3 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/puppet/master.pp @@ -0,0 +1,10 @@ +class shorewall::rules::puppet::master { +  shorewall::rule { 'net-me-tcp_puppet-main': +    source          => 'net', +    destination     => '$FW', +    proto           => 'tcp', +    destinationport => '$PUPPETSERVER_PORT,$PUPPETSERVER_SIGN_PORT', +    order           => 240, +    action          => 'ACCEPT'; +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/rsync.pp b/puppet/modules/shorewall/manifests/rules/rsync.pp new file mode 100644 index 00000000..144624db --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/rsync.pp @@ -0,0 +1,10 @@ +class shorewall::rules::rsync { +    shorewall::rule{'me-net-rsync-tcp': +        source          => '$FW', +        destination     => 'net', +        proto           => 'tcp', +        destinationport => '873', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/silcd.pp b/puppet/modules/shorewall/manifests/rules/silcd.pp new file mode 100644 index 00000000..91ee4a59 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/silcd.pp @@ -0,0 +1,19 @@ +class shorewall::rules::silcd { +  shorewall::rule{ +    'net-me-silcd-tcp': +      source          => 'net', +      destination     => '$FW', +      proto           => 'tcp', +      destinationport => '706', +      order           => 240, +      action          => 'ACCEPT'; +    'net-me-silcd-udp': +      source          => 'net', +      destination     => '$FW', +      proto           => 'udp', +      destinationport => '706', +      order           => 240, +      action          => 'ACCEPT'; + +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/smtp.pp b/puppet/modules/shorewall/manifests/rules/smtp.pp new file mode 100644 index 00000000..b0389012 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/smtp.pp @@ -0,0 +1,10 @@ +class shorewall::rules::smtp { +    shorewall::rule { 'net-me-smtp-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '25', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/smtp/disable.pp b/puppet/modules/shorewall/manifests/rules/smtp/disable.pp new file mode 100644 index 00000000..cee85b08 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/smtp/disable.pp @@ -0,0 +1,5 @@ +class shorewall::rules::smtp::disable inherits shorewall::rules::smtp { +  Shorewall::Rule['net-me-smtp-tcp']{ +    action          => 'DROP' +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/smtp_submission.pp b/puppet/modules/shorewall/manifests/rules/smtp_submission.pp new file mode 100644 index 00000000..dff90f35 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/smtp_submission.pp @@ -0,0 +1,10 @@ +class shorewall::rules::smtp_submission { +    shorewall::rule { 'net-me-smtp_submission-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '587', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/smtp_submission/disable.pp b/puppet/modules/shorewall/manifests/rules/smtp_submission/disable.pp new file mode 100644 index 00000000..9724fe79 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/smtp_submission/disable.pp @@ -0,0 +1,5 @@ +class shorewall::rules::smtp_submission::disable inherits shorewall::rules::smtp_submission { +  Shorewall::Rule['net-me-smtp_submission-tcp']{ +    action          => 'DROP' +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/smtps.pp b/puppet/modules/shorewall/manifests/rules/smtps.pp new file mode 100644 index 00000000..48183f74 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/smtps.pp @@ -0,0 +1,10 @@ +class shorewall::rules::smtps { +	shorewall::rule {'net-me-smtps-tcp': +        source          =>      'net', +        destination     =>      '$FW', +        proto           =>      'tcp', +        destinationport =>      '465', +        order           =>      240, +        action          =>      'ACCEPT'; +	} +} diff --git a/puppet/modules/shorewall/manifests/rules/smtps/disable.pp b/puppet/modules/shorewall/manifests/rules/smtps/disable.pp new file mode 100644 index 00000000..24bd21fb --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/smtps/disable.pp @@ -0,0 +1,5 @@ +class shorewall::rules::smtps::disable inherits shorewall::rules::smtps { +  Shorewall::Rule['net-me-smtps-tcp']{ +        action  => 'DROP', +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/sobby/instance.pp b/puppet/modules/shorewall/manifests/rules/sobby/instance.pp new file mode 100644 index 00000000..7151976b --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/sobby/instance.pp @@ -0,0 +1,11 @@ +define shorewall::rules::sobby::instance( $port ){ +  shorewall::rule { +    "net-me-tcp_sobby_${name}": +      source          => 'net', +      destination     => '$FW', +      proto           => 'tcp', +      destinationport => $port, +      order           => 240, +      action          => 'ACCEPT'; +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/ssh.pp b/puppet/modules/shorewall/manifests/rules/ssh.pp new file mode 100644 index 00000000..3a1b5309 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/ssh.pp @@ -0,0 +1,13 @@ +class shorewall::rules::ssh( +  $ports, +  $source = 'net' +) { +  shorewall::rule { 'net-me-tcp_ssh': +    source          => $shorewall::rules::ssh::source, +    destination     => '$FW', +    proto           => 'tcp', +    destinationport => join($shorewall::rules::ssh::ports,','), +    order           => 240, +    action          => 'ACCEPT'; +  } +} diff --git a/puppet/modules/shorewall/manifests/rules/syslog.pp b/puppet/modules/shorewall/manifests/rules/syslog.pp new file mode 100644 index 00000000..de802e25 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/syslog.pp @@ -0,0 +1,12 @@ +class shorewall::rules::syslog { +    shorewall::rule { 'net-me-syslog-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '514', +        order           => 240, +        action          => 'ACCEPT'; +    } +} + + diff --git a/puppet/modules/shorewall/manifests/rules/tftp.pp b/puppet/modules/shorewall/manifests/rules/tftp.pp new file mode 100644 index 00000000..78877293 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/tftp.pp @@ -0,0 +1,18 @@ +class shorewall::rules::tftp { +    shorewall::rule { 'net-me-tftp-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '69', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-tftp-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '69', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/tinc.pp b/puppet/modules/shorewall/manifests/rules/tinc.pp new file mode 100644 index 00000000..79cf92e4 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/tinc.pp @@ -0,0 +1,34 @@ +class shorewall::rules::tinc { +    shorewall::rule { 'net-me-tinc-tcp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'tcp', +        destinationport => '655', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'me-net-tinc-tcp': +        source          => '$FW', +        destination     => 'net', +        proto           => 'tcp', +        destinationport => '655', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'net-me-tinc-udp': +        source          => 'net', +        destination     => '$FW', +        proto           => 'udp', +        destinationport => '655', +        order           => 240, +        action          => 'ACCEPT'; +    } +    shorewall::rule { 'me-net-tinc-udp': +        source          => '$FW', +        destination     => 'net', +        proto           => 'udp', +        destinationport => '655', +        order           => 240, +        action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/tomcat.pp b/puppet/modules/shorewall/manifests/rules/tomcat.pp new file mode 100644 index 00000000..3c6f9df0 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/tomcat.pp @@ -0,0 +1,12 @@ +class shorewall::rules::tomcat { +    # open tomcat port +    shorewall::rule { +        'net-me-tomcat-tcp': +            source          => 'net', +            destination     => '$FW', +            proto           => 'tcp', +            destinationport => '8080', +            order           => 240, +            action          => 'ACCEPT'; +    } +} diff --git a/puppet/modules/shorewall/manifests/rules/torify.pp b/puppet/modules/shorewall/manifests/rules/torify.pp new file mode 100644 index 00000000..f6e62d81 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/torify.pp @@ -0,0 +1,29 @@ +# shorewall::rules::torify +# +# Note: shorewall::rules::torify cannot be used several times with the +# same user listed in the $users array. This restriction applies to +# using this define multiple times without providing a $users +# parameter. +# +# Parameters: +# +# - users: every element of this array must be valid in shorewall +#   rules user/group column. +# - destinations: every element of this array must be valid in +#   shorewall rules original destination column. + +define shorewall::rules::torify( +  $users        = ['-'], +  $destinations = ['-'], +  $allow_rfc1918 = true +){ + +  $originaldest = join($destinations,',') + +  shorewall::rules::torify::user { +    $users: +      originaldest  => $originaldest, +      allow_rfc1918 => $allow_rfc1918; +  } + +} diff --git a/puppet/modules/shorewall/manifests/rules/torify/allow_tor_transparent_proxy.pp b/puppet/modules/shorewall/manifests/rules/torify/allow_tor_transparent_proxy.pp new file mode 100644 index 00000000..3c18db69 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/torify/allow_tor_transparent_proxy.pp @@ -0,0 +1,21 @@ +class shorewall::rules::torify::allow_tor_transparent_proxy { + +  $rule = "allow-tor-transparent-proxy" + +  if !defined(Shorewall::Rule["$rule"]) { +    # A weirdness in shorewall forces us to explicitly allow traffic to +    # net:$tor_transparent_proxy_host:$tor_transparent_proxy_port even +    # if $FW->$FW traffic is allowed. This anyway avoids us special-casing +    # the remote Tor transparent proxy situation. +    shorewall::rule { +      "$rule": +        source          => '$FW', +        destination     => "net:${shorewall::tor_transparent_proxy_host}", +        proto           => 'tcp', +        destinationport => $shorewall::tor_transparent_proxy_port, +        order           => 100, +        action          => 'ACCEPT'; +    } +  } + +} diff --git a/puppet/modules/shorewall/manifests/rules/torify/allow_tor_user.pp b/puppet/modules/shorewall/manifests/rules/torify/allow_tor_user.pp new file mode 100644 index 00000000..f44c1f01 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/torify/allow_tor_user.pp @@ -0,0 +1,15 @@ +class shorewall::rules::torify::allow_tor_user { + +  $whitelist_rule = "allow-from-tor-user" +  if !defined(Shorewall::Rule["$whitelist_rule"]) { +    shorewall::rule { +      "$whitelist_rule": +        source      => '$FW', +        destination => 'all', +        user        => $shorewall::tor_user, +        order       => 101, +        action      => 'ACCEPT'; +    } +  } + +} diff --git a/puppet/modules/shorewall/manifests/rules/torify/redirect_tcp_to_tor.pp b/puppet/modules/shorewall/manifests/rules/torify/redirect_tcp_to_tor.pp new file mode 100644 index 00000000..2bee6584 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/torify/redirect_tcp_to_tor.pp @@ -0,0 +1,40 @@ +define shorewall::rules::torify::redirect_tcp_to_tor( +  $user = '-', +  $originaldest = '-' +){ + +  # hash the destination as it may contain slashes +  $originaldest_sha1 = sha1($originaldest) +  $rule = "redirect-to-tor-user=${user}-to=${originaldest_sha1}" + +  if !defined(Shorewall::Rule["$rule"]) { + +    $originaldest_real = $originaldest ? { +      '-'     => '!127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16', +      default => $originaldest, +    } + +    $user_real = $user ? { +      '-'     => "!${shorewall::tor_user}", +      default => $user, +    } + +    $destzone = $shorewall::tor_transparent_proxy_host ? { +      '127.0.0.1' => '$FW', +      default     => 'net' +    } +     +    shorewall::rule { +      "$rule": +        source       => '$FW', +        destination  => "${destzone}:${shorewall::tor_transparent_proxy_host}:${shorewall::tor_transparent_proxy_port}", +        proto        => 'tcp:syn', +        originaldest => $originaldest_real, +        user         => $user_real, +        order        => 110, +        action       => 'DNAT'; +    } + +  } + +} diff --git a/puppet/modules/shorewall/manifests/rules/torify/reject_non_tor.pp b/puppet/modules/shorewall/manifests/rules/torify/reject_non_tor.pp new file mode 100644 index 00000000..80240ec7 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/torify/reject_non_tor.pp @@ -0,0 +1,32 @@ +define shorewall::rules::torify::reject_non_tor( +  $user = '-', +  $originaldest = '-', +  $allow_rfc1918 = true +){ + +  # hash the destination as it may contain slashes +  $originaldest_sha1 = sha1($originaldest) +  $rule = "reject-non-tor-from-${user}-to=${originaldest_sha1}" + +  if $originaldest == '-' { +    $originaldest_real = $allow_rfc1918 ? { +      false   => '!127.0.0.1', +      default => '!127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16', +    } +  } else { +    $originaldest_real = $originaldest +  } + +  if !defined(Shorewall::Rule["$rule"]) { +    shorewall::rule { +      "$rule": +        source          => '$FW', +        destination     => 'all', +        originaldest    => $originaldest_real, +        user            => $user, +        order           => 120, +        action          => 'REJECT'; +    } +  } + +} diff --git a/puppet/modules/shorewall/manifests/rules/torify/user.pp b/puppet/modules/shorewall/manifests/rules/torify/user.pp new file mode 100644 index 00000000..5caccfd6 --- /dev/null +++ b/puppet/modules/shorewall/manifests/rules/torify/user.pp @@ -0,0 +1,27 @@ +define shorewall::rules::torify::user( +  $originaldest = '-', +  $allow_rfc1918 = true +){ + +  $user = $name + +  include shorewall::rules::torify::allow_tor_transparent_proxy + +  if $originaldest == '-' and $user == '-' { +    include shorewall::rules::torify::allow_tor_user +  } + +  shorewall::rules::torify::redirect_tcp_to_tor { +    "redirect-to-tor-user=${user}-to=${originaldest}": +      user         => $user, +      originaldest => $originaldest +  } + +  shorewall::rules::torify::reject_non_tor { +    "reject-non-tor-user=${user}-to=${originaldest}": +      user          => "$user", +      originaldest  => $originaldest, +      allow_rfc1918 => $allow_rfc1918; +  } + +} diff --git a/puppet/modules/shorewall/manifests/tcclasses.pp b/puppet/modules/shorewall/manifests/tcclasses.pp new file mode 100644 index 00000000..4e30a556 --- /dev/null +++ b/puppet/modules/shorewall/manifests/tcclasses.pp @@ -0,0 +1,12 @@ +define shorewall::tcclasses( +    $interface, +    $rate, +    $ceil, +    $priority, +    $options = '', +    $order = '1' +){ +    shorewall::entry { "tcclasses-${order}-${name}": +        line => "# ${name}\n${interface} ${order} ${rate} ${ceil} ${priority} ${options}", +    } +} diff --git a/puppet/modules/shorewall/manifests/tcdevices.pp b/puppet/modules/shorewall/manifests/tcdevices.pp new file mode 100644 index 00000000..f4e88d80 --- /dev/null +++ b/puppet/modules/shorewall/manifests/tcdevices.pp @@ -0,0 +1,11 @@ +define shorewall::tcdevices( +    $in_bandwidth, +    $out_bandwidth, +    $options = '', +    $redirected_interfaces = '', +    $order = '100' +){ +    shorewall::entry { "tcdevices-${order}-${name}": +        line => "${name} ${in_bandwidth} ${out_bandwidth} ${options} ${redirected_interfaces}", +    } +} diff --git a/puppet/modules/shorewall/manifests/tcrules.pp b/puppet/modules/shorewall/manifests/tcrules.pp new file mode 100644 index 00000000..b9ab4a9d --- /dev/null +++ b/puppet/modules/shorewall/manifests/tcrules.pp @@ -0,0 +1,12 @@ +define shorewall::tcrules( +    $source, +    $destination, +    $protocol = 'all', +    $ports, +    $client_ports = '', +    $order = '1' +){ +    shorewall::entry { "tcrules-${order}-${name}": +        line => "# ${name}\n${order} ${source} ${destination} ${protocol} ${ports} ${client_ports}", +    } +} diff --git a/puppet/modules/shorewall/manifests/tunnel.pp b/puppet/modules/shorewall/manifests/tunnel.pp new file mode 100644 index 00000000..2cac9227 --- /dev/null +++ b/puppet/modules/shorewall/manifests/tunnel.pp @@ -0,0 +1,11 @@ +define shorewall::tunnel( +    $tunnel_type, +    $zone, +    $gateway = '0.0.0.0/0', +    $gateway_zones = '', +    $order = '1' +) { +    shorewall::entry { "tunnel-${order}-${name}": +        line => "# ${name}\n${tunnel_type} ${zone} ${gateway} ${gateway_zones}", +    } +} diff --git a/puppet/modules/shorewall/manifests/ubuntu/karmic.pp b/puppet/modules/shorewall/manifests/ubuntu/karmic.pp new file mode 100644 index 00000000..0df37894 --- /dev/null +++ b/puppet/modules/shorewall/manifests/ubuntu/karmic.pp @@ -0,0 +1,5 @@ +class shorewall::ubuntu::karmic inherits shorewall::debian { +  Package['shorewall']{ +    name => 'shorewall-shell', +  } +} diff --git a/puppet/modules/shorewall/manifests/zone.pp b/puppet/modules/shorewall/manifests/zone.pp new file mode 100644 index 00000000..81e57711 --- /dev/null +++ b/puppet/modules/shorewall/manifests/zone.pp @@ -0,0 +1,14 @@ +define shorewall::zone( +    $type, +    $options = '-', +    $in = '-', +    $out = '-', +    $parent = '-', +    $order = 100 +){ +    $real_name = $parent ? { '-' => $name, default => "${name}:${parent}" } +    shorewall::entry { "zones-${order}-${name}": +        line => "${real_name} ${type} ${options} ${in} ${out}" +    } +} + diff --git a/puppet/modules/shorewall/templates/debian_default.erb b/puppet/modules/shorewall/templates/debian_default.erb new file mode 100644 index 00000000..ec64cbe0 --- /dev/null +++ b/puppet/modules/shorewall/templates/debian_default.erb @@ -0,0 +1,26 @@ +# prevent startup with default configuration +# set the following varible to 1 in order to allow Shorewall to start + +# This file is brought to you by puppet + +startup=<%= scope.lookupvar('shorewall::startup') == "0" ? '0' : '1' %> + +# if your Shorewall configuration requires detection of the ip address of a ppp +# interface, you must list such interfaces in "wait_interface" to get Shorewall to +# wait until the interface is configured. Otherwise the script will fail because +# it won't be able to detect the IP address. +# +# Example: +#    wait_interface="ppp0" +# or +#    wait_interface="ppp0 ppp1" +# or, if you have defined  in /etc/shorewall/params +#    wait_interface= + +# +# Startup options +# + +OPTIONS="" + +# EOF diff --git a/puppet/modules/site_apache/files/conf.d/security b/puppet/modules/site_apache/files/conf.d/security new file mode 100644 index 00000000..a5ae5bdc --- /dev/null +++ b/puppet/modules/site_apache/files/conf.d/security @@ -0,0 +1,55 @@ +# +# Disable access to the entire file system except for the directories that +# are explicitly allowed later. +# +# This currently breaks the configurations that come with some web application +# Debian packages. It will be made the default for the release after lenny. +# +#<Directory /> +#	AllowOverride None +#	Order Deny,Allow +#	Deny from all +#</Directory> + + +# Changing the following options will not really affect the security of the +# server, but might make attacks slightly more difficult in some cases. + +# +# ServerTokens +# This directive configures what you return as the Server HTTP response +# Header. The default is 'Full' which sends information about the OS-Type +# and compiled in modules. +# Set to one of:  Full | OS | Minimal | Minor | Major | Prod +# where Full conveys the most information, and Prod the least. +# +#ServerTokens Minimal +ServerTokens Prod + +# +# Optionally add a line containing the server version and virtual host +# name to server-generated pages (internal error documents, FTP directory +# listings, mod_status and mod_info output etc., but not CGI generated +# documents or custom error documents). +# Set to "EMail" to also include a mailto: link to the ServerAdmin. +# Set to one of:  On | Off | EMail +# +#ServerSignature Off +ServerSignature Off + +# +# Allow TRACE method +# +# Set to "extended" to also reflect the request body (only for testing and +# diagnostic purposes). +# +# Set to one of:  On | Off | extended +# +#TraceEnable Off +TraceEnable On + +# Setting this header will prevent other sites from embedding pages from this +# site as frames. This defends against clickjacking attacks. +# Requires mod_headers to be enabled. +# +Header set X-Frame-Options: "DENY" diff --git a/puppet/modules/site_apache/files/include.d/ssl_common.inc b/puppet/modules/site_apache/files/include.d/ssl_common.inc new file mode 100644 index 00000000..2d282c84 --- /dev/null +++ b/puppet/modules/site_apache/files/include.d/ssl_common.inc @@ -0,0 +1,7 @@ +SSLEngine on +SSLProtocol all -SSLv2 -SSLv3 +SSLHonorCipherOrder on +SSLCompression off +SSLCipherSuite "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!RC4:!MD5:!PSK!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA" + +RequestHeader set X_FORWARDED_PROTO 'https'
\ No newline at end of file diff --git a/puppet/modules/site_apache/manifests/common.pp b/puppet/modules/site_apache/manifests/common.pp new file mode 100644 index 00000000..8a11759a --- /dev/null +++ b/puppet/modules/site_apache/manifests/common.pp @@ -0,0 +1,30 @@ +# install basic apache modules needed for all services (nagios, webapp) +class site_apache::common { + +  include apache::module::rewrite +  include apache::module::env + +  class { '::apache': +    no_default_site  => true, +    ssl              => true, +    ssl_cipher_suite => 'HIGH:MEDIUM:!aNULL:!MD5' +  } + +  # needed for the mod_ssl config +  include apache::module::mime + +  # load mods depending on apache version +  if ( $::lsbdistcodename == 'jessie' ) { +    # apache >= 2.4, debian jessie +    # needed for mod_ssl config +    include apache::module::socache_shmcb +    # generally needed +    include apache::module::mpm_prefork +  } else { +    # apache < 2.4, debian wheezy +    # for "Order" directive, i.e. main apache2.conf +    include apache::module::authz_host +  } + +  include site_apache::common::tls +} diff --git a/puppet/modules/site_apache/manifests/common/tls.pp b/puppet/modules/site_apache/manifests/common/tls.pp new file mode 100644 index 00000000..040868bf --- /dev/null +++ b/puppet/modules/site_apache/manifests/common/tls.pp @@ -0,0 +1,6 @@ +class site_apache::common::tls { +  # class to setup common SSL configurations + +  apache::config::include{ 'ssl_common.inc': } + +} diff --git a/puppet/modules/site_apache/templates/vhosts.d/api.conf.erb b/puppet/modules/site_apache/templates/vhosts.d/api.conf.erb new file mode 100644 index 00000000..bfa5d04d --- /dev/null +++ b/puppet/modules/site_apache/templates/vhosts.d/api.conf.erb @@ -0,0 +1,48 @@ +<VirtualHost *:80> +  ServerName <%= @api_domain %> +  RewriteEngine On +  RewriteRule ^.*$ https://<%= @api_domain -%>:<%= @api_port -%>%{REQUEST_URI} [R=permanent,L] +  CustomLog ${APACHE_LOG_DIR}/other_vhosts_access.log common +</VirtualHost> + +Listen 0.0.0.0:<%= @api_port %> + +<VirtualHost *:<%= @api_port -%>> +  ServerName <%= @api_domain %> +  CustomLog ${APACHE_LOG_DIR}/other_vhosts_access.log common + +  SSLCACertificatePath /etc/ssl/certs +  SSLCertificateKeyFile <%= scope.lookupvar('x509::variables::keys') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.key +  SSLCertificateFile <%= scope.lookupvar('x509::variables::certs') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.crt + +  Include include.d/ssl_common.inc + +  <IfModule mod_headers.c> +<% if @webapp['secure'] -%> +    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" +<% end -%> +    Header always unset X-Powered-By +    Header always unset X-Runtime +  </IfModule> + +  DocumentRoot /srv/leap/webapp/public +  <% if scope.function_guess_apache_version([]) == '2.4' %> +  <Directory /srv/leap/webapp/public> +    AllowOverride None +    Require all granted +  </Directory> +  <% end %> + +  # Check for maintenance file and redirect all requests +  RewriteEngine On +  RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f +  RewriteCond %{SCRIPT_FILENAME} !maintenance.html +  RewriteCond %{REQUEST_URI} !/images/maintenance.jpg +  RewriteRule ^.*$ %{DOCUMENT_ROOT}/system/maintenance.html [L] + +  # http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerallowencodedslashes_lt_on_off_gt +  AllowEncodedSlashes on +  PassengerAllowEncodedSlashes on +  PassengerFriendlyErrorPages off +  SetEnv TMPDIR /var/tmp +</VirtualHost> diff --git a/puppet/modules/site_apache/templates/vhosts.d/common.conf.erb b/puppet/modules/site_apache/templates/vhosts.d/common.conf.erb new file mode 100644 index 00000000..bf60e794 --- /dev/null +++ b/puppet/modules/site_apache/templates/vhosts.d/common.conf.erb @@ -0,0 +1,76 @@ +<VirtualHost *:80> +  ServerName <%= @webapp_domain %> +  ServerAlias <%= @domain_name %> +  ServerAlias <%= @domain %> +  ServerAlias www.<%= @domain %> +  RewriteEngine On +  RewriteRule ^.*$ https://<%= @webapp_domain -%>%{REQUEST_URI} [R=permanent,L] +  CustomLog ${APACHE_LOG_DIR}/other_vhosts_access.log common +</VirtualHost> + +<VirtualHost *:443> +  ServerName <%= @webapp_domain %> +  ServerAlias <%= @domain_name %> +  ServerAlias <%= @domain %> +  ServerAlias www.<%= @domain %> +  CustomLog ${APACHE_LOG_DIR}/other_vhosts_access.log common + +  SSLCACertificatePath /etc/ssl/certs +  SSLCertificateKeyFile <%= scope.lookupvar('x509::variables::keys') %>/<%= scope.lookupvar('site_config::params::commercial_cert_name') %>.key +  SSLCertificateFile <%= scope.lookupvar('x509::variables::certs') %>/<%= scope.lookupvar('site_config::params::commercial_cert_name') %>.crt + +  Include include.d/ssl_common.inc + +  <IfModule mod_headers.c> +<% if (defined? @services) and (@services.include? 'webapp') and (@webapp['secure']) -%> +    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" +<% end -%> +    Header always unset X-Powered-By +    Header always unset X-Runtime +  </IfModule> + +<% if (defined? @services) and (@services.include? 'webapp') -%> +  DocumentRoot /srv/leap/webapp/public +  <% if scope.function_guess_apache_version([]) == '2.4' %> +  <Directory /srv/leap/webapp/public> +    AllowOverride None +    Require all granted +  </Directory> +  <% end %> + +  RewriteEngine On +  # Check for maintenance file and redirect all requests +  RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f +  RewriteCond %{SCRIPT_FILENAME} !maintenance.html +  RewriteCond %{REQUEST_URI} !/images/maintenance.jpg +  RewriteRule ^.*$ %{DOCUMENT_ROOT}/system/maintenance.html [L] + +  # http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerallowencodedslashes_lt_on_off_gt +  AllowEncodedSlashes on +  PassengerAllowEncodedSlashes on +  PassengerFriendlyErrorPages off +  SetEnv TMPDIR /var/tmp + +  # Allow rails assets to be cached for a very long time (since the URLs change whenever the content changes) +  <Location /assets/> +    Header unset ETag +    FileETag None +    ExpiresActive On +    ExpiresDefault "access plus 1 year" +  </Location> +<% end -%> + + +<% if (defined? @services) and (@services.include? 'monitor') -%> + <DirectoryMatch (/usr/share/nagios3/htdocs|/usr/lib/cgi-bin/nagios3|/etc/nagios3/stylesheets|/usr/share/pnp4nagios)> + <% if (defined? @services) and (@services.include? 'webapp') -%> +    PassengerEnabled off + <% end -%> +    AllowOverride all +    # Nagios won't work with setting this option to "DENY", +    # as set in conf.d/security (#4169). Therefor we allow +    # it here, only for nagios. +    Header set X-Frame-Options: "ALLOW" +  </DirectoryMatch> +<% end -%> +</VirtualHost> diff --git a/puppet/modules/site_apache/templates/vhosts.d/hidden_service.conf.erb b/puppet/modules/site_apache/templates/vhosts.d/hidden_service.conf.erb new file mode 100644 index 00000000..232b1577 --- /dev/null +++ b/puppet/modules/site_apache/templates/vhosts.d/hidden_service.conf.erb @@ -0,0 +1,55 @@ +<VirtualHost 127.0.0.1:80> +  ServerName <%= @tor_domain %> + +  <IfModule mod_headers.c> +    Header always unset X-Powered-By +    Header always unset X-Runtime +  </IfModule> + +<% if (defined? @services) and (@services.include? 'webapp') -%> +  DocumentRoot /srv/leap/webapp/public +  <% if scope.function_guess_apache_version([]) == '2.4' %> +  <Directory /srv/leap/webapp/public> +    AllowOverride None +    Require all granted +  </Directory> +  <% end %> + +  RewriteEngine On +  # Check for maintenance file and redirect all requests +  RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f +  RewriteCond %{SCRIPT_FILENAME} !maintenance.html +  RewriteCond %{REQUEST_URI} !/images/maintenance.jpg +  RewriteRule ^.*$ %{DOCUMENT_ROOT}/system/maintenance.html [L] + +  # http://www.modrails.com/documentation/Users%20guide%20Apache.html#_passengerallowencodedslashes_lt_on_off_gt +  AllowEncodedSlashes on +  PassengerAllowEncodedSlashes on +  PassengerFriendlyErrorPages off +  SetEnv TMPDIR /var/tmp + +  # Allow rails assets to be cached for a very long time (since the URLs change whenever the content changes) +  <Location /assets/> +    Header unset ETag +    FileETag None +    ExpiresActive On +    ExpiresDefault "access plus 1 year" +  </Location> +<% end -%> + +<% if (defined? @services) and (@services.include? 'static') -%> +  DocumentRoot "/srv/static/root/public" +  <% if scope.function_guess_apache_version([]) == '2.4' %> +  <Directory /srv/static/root/public> +    AllowOverride None +    Require all granted +  </Directory> +  <% end %> +  AccessFileName .htaccess + +  Alias /provider.json /srv/leap/provider.json +  <Location /provider.json> +    Header set X-Minimum-Client-Version 0.5 +  </Location> +<% end -%> +</VirtualHost> diff --git a/puppet/modules/site_apt/files/Debian/51unattended-upgrades-leap b/puppet/modules/site_apt/files/Debian/51unattended-upgrades-leap new file mode 100644 index 00000000..bbaac6a2 --- /dev/null +++ b/puppet/modules/site_apt/files/Debian/51unattended-upgrades-leap @@ -0,0 +1,6 @@ +// this file is managed by puppet ! + +Unattended-Upgrade::Allowed-Origins { +  "leap.se:stable"; +} + diff --git a/puppet/modules/site_apt/files/keys/leap-archive.gpg b/puppet/modules/site_apt/files/keys/leap-archive.gpg Binary files differnew file mode 100644 index 00000000..dd7f3be6 --- /dev/null +++ b/puppet/modules/site_apt/files/keys/leap-archive.gpg diff --git a/puppet/modules/site_apt/files/keys/leap-experimental-archive.gpg b/puppet/modules/site_apt/files/keys/leap-experimental-archive.gpg Binary files differnew file mode 100644 index 00000000..5cc9064b --- /dev/null +++ b/puppet/modules/site_apt/files/keys/leap-experimental-archive.gpg diff --git a/puppet/modules/site_apt/manifests/dist_upgrade.pp b/puppet/modules/site_apt/manifests/dist_upgrade.pp new file mode 100644 index 00000000..0eb98cea --- /dev/null +++ b/puppet/modules/site_apt/manifests/dist_upgrade.pp @@ -0,0 +1,17 @@ +# upgrade all packages +class site_apt::dist_upgrade { + +  # facter returns 'true' as string +  # lint:ignore:quoted_booleans +  if $::apt_running == 'true' { +  # lint:endignore +    fail ('apt-get is running in background - Please wait until it finishes. Exiting.') +  } else { +    exec{'initial_apt_dist_upgrade': +      command     => "/usr/bin/apt-get -q -y -o 'DPkg::Options::=--force-confold'  dist-upgrade", +      refreshonly => false, +      timeout     => 1200, +      require     => Exec['apt_updated'] +    } +  } +} diff --git a/puppet/modules/site_apt/manifests/init.pp b/puppet/modules/site_apt/manifests/init.pp new file mode 100644 index 00000000..455425c1 --- /dev/null +++ b/puppet/modules/site_apt/manifests/init.pp @@ -0,0 +1,55 @@ +# setup apt on all nodes +class site_apt { + +  $sources           = hiera('sources') +  $apt_config        = $sources['apt'] + +  # debian repo urls +  $apt_url_basic     = $apt_config['basic'] +  $apt_url_security  = $apt_config['security'] +  $apt_url_backports = $apt_config['backports'] + +  # leap repo url +  $platform_sources       = $sources['platform'] +  $apt_url_platform_basic = $platform_sources['apt']['basic'] + +  # needed on jessie hosts for getting pnp4nagios from testing +  if ( $::operatingsystemmajrelease == '8' ) { +    $use_next_release = true +  } else { +    $use_next_release = false +  } + +  class { 'apt': +    custom_key_dir   => 'puppet:///modules/site_apt/keys', +    debian_url       => $apt_url_basic, +    security_url     => $apt_url_security, +    backports_url    => $apt_url_backports, +    use_next_release => $use_next_release +  } + +  # enable http://deb.leap.se debian package repository +  include site_apt::leap_repo + +  apt::apt_conf { '90disable-pdiffs': +    content => 'Acquire::PDiffs "false";'; +  } + +  include ::site_apt::unattended_upgrades + +  # not currently used +  #apt::sources_list { 'secondary.list': +  #  content => template('site_apt/secondary.list'); +  #} + +  apt::preferences_snippet { 'leap': +    priority => 999, +    package  => '*', +    pin      => 'origin "deb.leap.se"' +  } + +  # All packages should be installed after 'update_apt' is called, +  # which does an 'apt-get update'. +  Exec['update_apt'] -> Package <||> + +} diff --git a/puppet/modules/site_apt/manifests/leap_repo.pp b/puppet/modules/site_apt/manifests/leap_repo.pp new file mode 100644 index 00000000..5eedce45 --- /dev/null +++ b/puppet/modules/site_apt/manifests/leap_repo.pp @@ -0,0 +1,16 @@ +# install leap deb repo together with leap-keyring package +# containing the apt signing key +class site_apt::leap_repo { +  $platform = hiera_hash('platform') +  $major_version = $platform['major_version'] + +  apt::sources_list { 'leap.list': +    content => "deb ${::site_apt::apt_url_platform_basic} ${::lsbdistcodename} main\n", +    before  => Exec[refresh_apt] +  } + +  package { 'leap-archive-keyring': +    ensure => latest +  } + +} diff --git a/puppet/modules/site_apt/manifests/preferences/check_mk.pp b/puppet/modules/site_apt/manifests/preferences/check_mk.pp new file mode 100644 index 00000000..580e0d3f --- /dev/null +++ b/puppet/modules/site_apt/manifests/preferences/check_mk.pp @@ -0,0 +1,9 @@ +class site_apt::preferences::check_mk { + +  apt::preferences_snippet { 'check-mk': +    package  => 'check-mk-*', +    release  => "${::lsbdistcodename}-backports", +    priority => 999; +  } + +} diff --git a/puppet/modules/site_apt/manifests/preferences/passenger.pp b/puppet/modules/site_apt/manifests/preferences/passenger.pp new file mode 100644 index 00000000..8cd41f91 --- /dev/null +++ b/puppet/modules/site_apt/manifests/preferences/passenger.pp @@ -0,0 +1,14 @@ +# +# currently, this is only used by static_site to get passenger v4. +# +# UPGRADE: this is not needed for jessie. +# +class site_apt::preferences::passenger { + +  apt::preferences_snippet { 'passenger': +    package  => 'libapache2-mod-passenger', +    release  => "${::lsbdistcodename}-backports", +    priority => 999; +  } + +} diff --git a/puppet/modules/site_apt/manifests/preferences/rsyslog.pp b/puppet/modules/site_apt/manifests/preferences/rsyslog.pp new file mode 100644 index 00000000..bfeaa7da --- /dev/null +++ b/puppet/modules/site_apt/manifests/preferences/rsyslog.pp @@ -0,0 +1,13 @@ +class site_apt::preferences::rsyslog { + +  apt::preferences_snippet { +    'rsyslog_anon_depends': +      package  => 'libestr0 librelp0 rsyslog*', +      priority => '999', +      pin      => 'release a=wheezy-backports', +      before   => Class['rsyslog::install']; + +    'fixed_rsyslog_anon_package': +      ensure => absent; +  } +} diff --git a/puppet/modules/site_apt/manifests/unattended_upgrades.pp b/puppet/modules/site_apt/manifests/unattended_upgrades.pp new file mode 100644 index 00000000..42f1f4c6 --- /dev/null +++ b/puppet/modules/site_apt/manifests/unattended_upgrades.pp @@ -0,0 +1,20 @@ +# configute unattended upgrades so packages from both Debian and LEAP +# repos get upgraded unattended +class site_apt::unattended_upgrades { +  # override unattended-upgrades package resource to make sure +  # that it is upgraded on every deploy (#6245) + +  # configure upgrades for Debian +  class { 'apt::unattended_upgrades': +    ensure_version => latest +  } + +  # configure LEAP upgrades +  apt::apt_conf { '51unattended-upgrades-leap': +    source      => [ +      "puppet:///modules/site_apt/${::lsbdistid}/51unattended-upgrades-leap"], +    require     => Package['unattended-upgrades'], +    refresh_apt => false, +  } + +} diff --git a/puppet/modules/site_apt/templates/jessie/postfix.seeds b/puppet/modules/site_apt/templates/jessie/postfix.seeds new file mode 100644 index 00000000..1a878ccc --- /dev/null +++ b/puppet/modules/site_apt/templates/jessie/postfix.seeds @@ -0,0 +1 @@ +postfix	postfix/main_mailer_type	select	No configuration diff --git a/puppet/modules/site_apt/templates/preferences.include_squeeze b/puppet/modules/site_apt/templates/preferences.include_squeeze new file mode 100644 index 00000000..d6d36b60 --- /dev/null +++ b/puppet/modules/site_apt/templates/preferences.include_squeeze @@ -0,0 +1,25 @@ +Explanation: Debian wheezy +Package: * +Pin: release o=Debian,n=wheezy +Pin-Priority: 990 + +Explanation: Debian wheezy-updates +Package: * +Pin: release o=Debian,n=wheezy-updates +Pin-Priority: 990 + +Explanation: Debian sid +Package: * +Pin: release o=Debian,n=sid +Pin-Priority: 1 + +Explanation: Debian squeeze +Package: * +Pin: release o=Debian,n=squeeze +Pin-Priority: 980 + +Explanation: Debian fallback +Package: * +Pin: release o=Debian +Pin-Priority: -10 + diff --git a/puppet/modules/site_apt/templates/secondary.list b/puppet/modules/site_apt/templates/secondary.list new file mode 100644 index 00000000..0c024549 --- /dev/null +++ b/puppet/modules/site_apt/templates/secondary.list @@ -0,0 +1,3 @@ +# basic +deb http://ftp.debian.org/debian/ <%= @lsbdistcodename %> main contrib non-free + diff --git a/puppet/modules/site_apt/templates/wheezy/postfix.seeds b/puppet/modules/site_apt/templates/wheezy/postfix.seeds new file mode 100644 index 00000000..1a878ccc --- /dev/null +++ b/puppet/modules/site_apt/templates/wheezy/postfix.seeds @@ -0,0 +1 @@ +postfix	postfix/main_mailer_type	select	No configuration diff --git a/puppet/modules/site_check_mk/files/agent/local_checks/all_hosts/run_node_tests.sh b/puppet/modules/site_check_mk/files/agent/local_checks/all_hosts/run_node_tests.sh new file mode 100644 index 00000000..1dd0afc9 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/local_checks/all_hosts/run_node_tests.sh @@ -0,0 +1,5 @@ +#!/bin/sh +# +# runs node tests + +/srv/leap/bin/run_tests --checkmk diff --git a/puppet/modules/site_check_mk/files/agent/local_checks/couchdb/leap_couch_stats.sh b/puppet/modules/site_check_mk/files/agent/local_checks/couchdb/leap_couch_stats.sh new file mode 100755 index 00000000..c7477b18 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/local_checks/couchdb/leap_couch_stats.sh @@ -0,0 +1,122 @@ +#!/bin/bash +# +# todo: +#  - thresholds +#  - couch response time +#  - make CURL/URL/DBLIST_EXCLUDE vars configurable +#  - move load_nagios_utils() to helper library so we can use it from multiple scripts + +start_time=$(date +%s.%N) + +CURL='curl -s --netrc-file /etc/couchdb/couchdb.netrc' +URL='http://127.0.0.1:5984' +TMPFILE=$(mktemp) +DBLIST_EXCLUDE='(user-|sessions_|tokens_|_replicator|_users)' +PREFIX='Couchdb_' + + +load_nagios_utils () { +  # load the nagios utils +  # in debian, the package nagios-plugins-common installs utils.sh to /usr/lib/nagios/plugins/utils.sh +  utilsfn= +  for d in $PROGPATH /usr/lib/nagios/plugins /usr/lib64/nagios/plugins /usr/local/nagios/libexec /opt/nagios-plugins/libexec . ; do +    if [ -f "$d/utils.sh" ]; then +      utilsfn=$d/utils.sh; +    fi +  done +  if [ "$utilsfn" = "" ]; then +    echo "UNKNOWN - cannot find utils.sh (part of nagios plugins)"; +    exit 3; +  fi +  . "$utilsfn"; +  STATE[$STATE_OK]='OK' +  STATE[$STATE_WARNING]='Warning' +  STATE[$STATE_CRITICAL]='Critical' +  STATE[$STATE_UNKNOWN]='Unknown' +  STATE[$STATE_DEPENDENT]='Dependend' +} + +get_global_stats_perf () { +  trap "localexit=3" ERR +  local localexit db_count +  localexit=0 + +  # get a list of all dbs +  $CURL -X GET $URL/_all_dbs | json_pp | egrep -v '(\[|\])' > $TMPFILE + +  db_count=$( wc -l < $TMPFILE) +  excluded_db_count=$( egrep -c "$DBLIST_EXCLUDE" $TMPFILE ) + +  echo "db_count=$db_count|excluded_db_count=$excluded_db_count" +  return ${localexit} +} + +db_stats () { +  trap "localexit=3" ERR +  local db db_stats doc_count del_doc_count localexit +  localexit=0 + +  db="$1" +  name="$2" + +  if [ -z "$name" ] +  then +    name="$db" +  fi + +  perf="$perf|${db}_docs=$( $CURL -s -X GET ${URL}/$db | json_pp |grep 'doc_count' | sed 's/[^0-9]//g' )" +  db_stats=$( $CURL -s -X GET ${URL}/$db | json_pp ) + +  doc_count=$( echo "$db_stats" | grep 'doc_count' | grep -v 'deleted_doc_count' | sed 's/[^0-9]//g' ) +  del_doc_count=$( echo "$db_stats" | grep 'doc_del_count' | sed 's/[^0-9]//g' ) + +  # don't divide by zero +  if [ $del_doc_count -eq 0 ] +  then +    del_doc_perc=0 +  else +    del_doc_perc=$(( del_doc_count * 100 / doc_count )) +  fi + +  bytes=$( echo "$db_stats" | grep disk_size | sed 's/[^0-9]//g' ) +  disk_size=$( echo "scale = 2; $bytes / 1024 / 1024" | bc -l ) + +  echo -n "${localexit} ${PREFIX}${name}_database ${name}_docs=$doc_count|${name}_deleted_docs=$del_doc_count|${name}_deleted_docs_percentage=${del_doc_perc}%" +  printf "|${name}_disksize_mb=%02.2fmb ${STATE[localexit]}: database $name\n" "$disk_size" + +  return ${localexit} +} + +# main + +load_nagios_utils + +# per-db stats +# get a list of all dbs +$CURL -X GET $URL/_all_dbs | json_pp | egrep -v '(\[|\])' > $TMPFILE + +# get list of dbs to check +dbs=$( egrep -v "${DBLIST_EXCLUDE}" $TMPFILE | tr -d '\n"' | sed 's/,/ /g' ) + +for db in $dbs +do +  db_stats "$db" +done + +# special handling for rotated dbs +suffix=$(($(date +'%s') / (60*60*24*30))) +db_stats "sessions_${suffix}" "sessions" +db_stats "tokens_${suffix}" "tokens" + + +# show global couchdb stats +global_stats_perf=$(get_global_stats_perf) +exitcode=$? + +end_time=$(date +%s.%N) +duration=$( echo "scale = 2; $end_time - $start_time" | bc -l ) + +printf "${exitcode} ${PREFIX}global_stats ${global_stats_perf}|script_duration=%02.2fs ${STATE[exitcode]}: global couchdb status\n" "$duration" + +rm "$TMPFILE" + diff --git a/puppet/modules/site_check_mk/files/agent/local_checks/mx/check_leap_mx.sh b/puppet/modules/site_check_mk/files/agent/local_checks/mx/check_leap_mx.sh new file mode 100755 index 00000000..4711e247 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/local_checks/mx/check_leap_mx.sh @@ -0,0 +1,33 @@ +#!/bin/bash + + +WARN=1 +CRIT=5 + +# in minutes +MAXAGE=10 + +STATUS[0]='OK' +STATUS[1]='Warning' +STATUS[2]='Critical' +CHECKNAME='Leap_MX_Queue' + +WATCHDIR='/var/mail/leap-mx/Maildir/new/' + + +total=`find $WATCHDIR -type f -mmin +$MAXAGE | wc -l` + +if [ $total -lt $WARN ] +then +  exitcode=0 +else +  if [ $total -le $CRIT ] +  then +    exitcode=1 +  else +      exitcode=2 +  fi +fi + +echo "${exitcode} ${CHECKNAME} stale_files=${total} ${STATUS[exitcode]}: ${total} stale files (>=${MAXAGE} min) in ${WATCHDIR}." + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/bigcouch.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/bigcouch.cfg new file mode 100644 index 00000000..0f378a5a --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/bigcouch.cfg @@ -0,0 +1,28 @@ +/opt/bigcouch/var/log/bigcouch.log nocontext=1 +# ignore requests that are fine + I undefined - -.*200$ + I undefined - -.*201$ + I 127.0.0.1 undefined.* ok + I 127.0.0.1 localhost:5984 .* ok + # https://leap.se/code/issues/5246 + I Shutting down group server + # ignore bigcouch conflict errors + I Error in process.*{{nocatch,conflict} + # ignore "Uncaught error in HTTP request: {exit, normal}" error + # it's suppressed in later versions of bigcouch anhow + # see https://leap.se/code/issues/5226 + I Uncaught error in HTTP request: {exit,normal} + I Uncaught error in HTTP request: {exit, + # Ignore rexi_EXIT bigcouch error (Bug #6512)  + I Error in process <[0-9.]+> on node .* with exit value: {{rexi_EXIT,{(killed|noproc|shutdown),\[{couch_db,collect_results + # Ignore "Generic server terminating" bigcouch message (Feature #6544) + I Generic server <.*> terminating + I {error_report,<.*>, + I {error_info, + C Uncaught error in HTTP request: {error, + C Response abnormally terminated: {nodedown, + C rexi_DOWN,noproc + C rexi_DOWN,noconnection + C error + C Connection attempt from disallowed node + W Apache CouchDB has started diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/leap_mx.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/leap_mx.cfg new file mode 100644 index 00000000..166d0230 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/leap_mx.cfg @@ -0,0 +1,4 @@ +/var/log/leap/mx.log + W Don't know how to deliver mail + W No public key, stopping the processing chain + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/logwatch.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/logwatch.cfg new file mode 100644 index 00000000..4f16d1bd --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/logwatch.cfg @@ -0,0 +1,31 @@ +# This file is managed by Puppet. DO NOT EDIT. + +# logwatch.cfg +# This file configures mk_logwatch. Define your logfiles +# and patterns to be looked for here. + +# Name one or more logfiles +/var/log/messages +# Patterns are indented with one space are prefixed with: +# C: Critical messages +# W: Warning messages +# I: ignore these lines (OK) +# The first match decided. Lines that do not match any pattern +# are ignored + C Fail event detected on md device + I mdadm.*: Rebuild.*event detected + W mdadm\[ + W ata.*hard resetting link + W ata.*soft reset failed (.*FIS failed) + W device-mapper: thin:.*reached low water mark + C device-mapper: thin:.*no free space + +/var/log/auth.log + W sshd.*Corrupted MAC on input + +/var/log/kern.log + C panic + C Oops + W generic protection rip + W .*Unrecovered read error - auto reallocate failed + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/openvpn.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/openvpn.cfg new file mode 100644 index 00000000..d99dcde9 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/openvpn.cfg @@ -0,0 +1,19 @@ +/var/log/leap/openvpn.log +# ignore openvpn TLS initialization errors when clients +# suddenly hangup before properly establishing +# a tls connection + I ovpn-.*TLS Error: Unroutable control packet received from + I ovpn-.*TLS Error: TLS key negotiation failed to occur within 60 seconds \(check your network connectivity\) + I ovpn-.*TLS Error: TLS handshake failed + I ovpn-.*TLS Error: TLS object -> incoming plaintext read error + I ovpn-.*Fatal TLS error \(check_tls_errors_co\), restarting + I ovpn-.*TLS_ERROR: BIO read tls_read_plaintext error: error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate + I ovpn-.*TLS_ERROR: BIO read tls_read_plaintext error: error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate + I ovpn-.*TLS Error: unknown opcode received from + I ovpn-.*Authenticate/Decrypt packet error: packet HMAC authentication failed + I ovpn-.*TLS Error: reading acknowledgement record from packet + I ovpn-.*TLS Error: session-id not found in packet from + + I ovpn-.*SIGUSR1\[soft,tls-error\] received, client-instance restarting + I ovpn-.*VERIFY ERROR: depth=0, error=certificate has expired + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/soledad.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/soledad.cfg new file mode 100644 index 00000000..3af5045b --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/soledad.cfg @@ -0,0 +1,6 @@ +/var/log/soledad.log + C WSGI application error + C Error + C error +# Removed this line because we determined it was better to ignore it (#6566) +# W Timing out client:  diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/stunnel.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/stunnel.cfg new file mode 100644 index 00000000..b1e6cf2f --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/stunnel.cfg @@ -0,0 +1,10 @@ +/var/log/leap/stunnel.log +# check for stunnel failures +# +# these are temporary failures and happen very often, so we +# ignore them until we tuned stunnel timeouts/logging, +# see https://leap.se/code/issues/5218 + I stunnel:.*Connection reset by peer + I stunnel:.*Peer suddenly disconnected + I stunnel:.*Connection refused + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/syslog/bigcouch.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/bigcouch.cfg new file mode 100644 index 00000000..f53f0780 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/bigcouch.cfg @@ -0,0 +1,5 @@ +# on one-node bigcouch setups, we'll get this msg +# a lot, so we ignore it here until we fix +# https://leap.se/code/issues/5244 + I epmd: got partial packet only on file descriptor + diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/syslog/couchdb.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/couchdb.cfg new file mode 100644 index 00000000..5f8d5b95 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/syslog/couchdb.cfg @@ -0,0 +1,2 @@ + C /usr/local/bin/couch-doc-update.*failed + C /usr/local/bin/couch-doc-update.*ERROR diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/syslog_header.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/syslog_header.cfg new file mode 100644 index 00000000..f60d752b --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/syslog_header.cfg @@ -0,0 +1 @@ +/var/log/syslog diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/syslog_tail.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/syslog_tail.cfg new file mode 100644 index 00000000..7daf0cac --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/syslog_tail.cfg @@ -0,0 +1,21 @@ +# some general patterns + I Error: Driver 'pcspkr' is already registered, aborting... +# ignore postfix errors on lost connection (Bug #6476) + I postfix/smtpd.*SSL_accept error from.*lost connection +# ignore postfix too many errors after DATA (#6545) + I postfix/smtpd.*too many errors after DATA from + C panic + C Oops + C Error +# ignore ipv6 icmp errors for now (Bug #6540) + I kernel: .*icmpv6_send: no reply to icmp error + C error + W generic protection rip + W .*Unrecovered read error - auto reallocate failed +# 401 Unauthorized error logged by webapp and possible other +# applications + C Unauthorized +# catch abnormal termination of processes (due to segfault/fpe +# signals etc). +# see https://github.com/pixelated/pixelated-user-agent/issues/683 + C systemd.*: main process exited, code=killed, status= diff --git a/puppet/modules/site_check_mk/files/agent/logwatch/webapp.cfg b/puppet/modules/site_check_mk/files/agent/logwatch/webapp.cfg new file mode 100644 index 00000000..337d9ec6 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/logwatch/webapp.cfg @@ -0,0 +1,8 @@ +/var/log/leap/webapp.log +# check for webapp errors + C Completed 500 +# couch connection issues + C webapp.*Could not connect to couch database messages due to 401 Unauthorized: {"error":"unauthorized","reason":"You are not a server admin."} +# ignore RoutingErrors that rails throw when it can't handle a url +# see https://leap.se/code/issues/5173 + I webapp.*ActionController::RoutingError diff --git a/puppet/modules/site_check_mk/files/agent/nagios_plugins/check_unix_open_fds.pl b/puppet/modules/site_check_mk/files/agent/nagios_plugins/check_unix_open_fds.pl new file mode 100755 index 00000000..06163d49 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/nagios_plugins/check_unix_open_fds.pl @@ -0,0 +1,322 @@ +#!/usr/bin/perl -w + +# check_unix_open_fds Nagios Plugin +# +# TComm - Carlos Peris Pla +# +# This nagios plugin is free software, and comes with ABSOLUTELY  +# NO WARRANTY. It may be used, redistributed and/or modified under  +# the terms of the GNU General Public Licence (see  +# http://www.fsf.org/licensing/licenses/gpl.txt). + + +# MODULE DECLARATION + +use strict; +use Nagios::Plugin; + + +# FUNCTION DECLARATION + +sub CreateNagiosManager (); +sub CheckArguments (); +sub PerformCheck (); + + +# CONSTANT DEFINITION + +use constant NAME => 	'check_unix_open_fds'; +use constant VERSION => '0.1b'; +use constant USAGE => 	"Usage:\ncheck_unix_open_fds -w <process_threshold,application_threshold> -c <process_threshold,application_threshold>\n". +						"\t\t[-V <version>]\n"; +use constant BLURB => 	"This plugin checks, in UNIX systems with the command lsof installed and with its SUID bit activated, the number\n". +						"of file descriptors opened by an application and its processes.\n"; +use constant LICENSE => "This nagios plugin is free software, and comes with ABSOLUTELY\n". +						"no WARRANTY. It may be used, redistributed and/or modified under\n". +						"the terms of the GNU General Public Licence\n". +						"(see http://www.fsf.org/licensing/licenses/gpl.txt).\n"; +use constant EXAMPLE => "\n\n". +						"Example:\n". +						"\n". +						"check_unix_open_fds -a /usr/local/nagios/bin/ndo2db -w 20,75 -c 25,85\n". +						"\n". +						"It returns CRITICAL if number of file descriptors opened by ndo2db is higher than 85,\n". +						"if not it returns WARNING if number of file descriptors opened by ndo2db is higher \n". +						"than 75, if not it returns CRITICAL if number of file descriptors opened by any process\n". +						"of ndo2db is higher than 25, if not it returns WARNING if number of file descriptors \n". +						"opened by any process of ndo2db is higher than 20.\n". +						"In other cases it returns OK if check has been performed succesfully.\n\n"; + +								 +# VARIABLE DEFINITION + +my $Nagios; +my $Error; +my $PluginResult; +my $PluginOutput; +my @WVRange; +my @CVRange; + + +# MAIN FUNCTION + +# Get command line arguments +$Nagios = &CreateNagiosManager(USAGE, VERSION, BLURB, LICENSE, NAME, EXAMPLE); +eval {$Nagios->getopts}; + +if (!$@) { +	# Command line parsed +	if (&CheckArguments($Nagios, \$Error, \@WVRange, \@CVRange)) { +		# Argument checking passed +		$PluginResult = &PerformCheck($Nagios, \$PluginOutput, \@WVRange, \@CVRange) +	} +	else { +		# Error checking arguments +		$PluginOutput = $Error; +		$PluginResult = UNKNOWN; +	} +	$Nagios->nagios_exit($PluginResult,$PluginOutput); +} +else { +	# Error parsing command line +	$Nagios->nagios_exit(UNKNOWN,$@); +} + +		 +	 +# FUNCTION DEFINITIONS + +# Creates and configures a Nagios plugin object +# Input: strings (usage, version, blurb, license, name and example) to configure argument parsing functionality +# Return value: reference to a Nagios plugin object + +sub CreateNagiosManager() { +	# Create GetOpt object +	my $Nagios = Nagios::Plugin->new(usage => $_[0], version =>  $_[1], blurb =>  $_[2], license =>  $_[3], plugin =>  $_[4], extra =>  $_[5]); +	 +	# Add argument units +	$Nagios->add_arg(spec => 'application|a=s', +				help => 'Application path for which you want to check the number of open file descriptors', +				required => 1);				 +	 +	# Add argument warning +	$Nagios->add_arg(spec => 'warning|w=s', +				help => "Warning thresholds. Format: <process_threshold,application_threshold>", +				required => 1); +	# Add argument critical +	$Nagios->add_arg(spec => 'critical|c=s', +				help => "Critical thresholds. Format: <process_threshold,application_threshold>", +				required => 1); +								 +	# Return value +	return $Nagios; +} + + +# Checks argument values and sets some default values +# Input: Nagios Plugin object +# Output: reference to Error description string, Memory Unit, Swap Unit, reference to WVRange ($_[4]), reference to CVRange ($_[5]) +# Return value: True if arguments ok, false if not + +sub CheckArguments() { +	my ($Nagios, $Error, $WVRange, $CVRange) = @_; +	my $commas; +	my $units; +	my $i; +	my $firstpos; +	my $secondpos; +	 +	# Check Warning thresholds list +	$commas = $Nagios->opts->warning =~ tr/,//;  +	if ($commas !=1){ +		${$Error} = "Invalid Warning list format. One comma is expected."; +		return 0; +	} +	else{ +		$i=0; +		$firstpos=0; +		my $warning=$Nagios->opts->warning; +		while ($warning =~ /[,]/g) { +			$secondpos=pos $warning; +			if ($secondpos - $firstpos==1){ +				@{$WVRange}[$i] = "~:"; +			}		 +			else{ +				@{$WVRange}[$i] = substr $Nagios->opts->warning, $firstpos, ($secondpos-$firstpos-1); +			} +			$firstpos=$secondpos; +			$i++ +		} +		if (length($Nagios->opts->warning) - $firstpos==0){#La coma es el ultimo elemento del string +			@{$WVRange}[$i] = "~:"; +		} +		else{ +			@{$WVRange}[$i] = substr $Nagios->opts->warning, $firstpos, (length($Nagios->opts->warning)-$firstpos); +		}	 +		 +		if (@{$WVRange}[0] !~/^(@?(\d+|(\d+|~):(\d+)?))?$/){ +			${$Error} = "Invalid Process Warning threshold in ${$WVRange[0]}"; +			return 0; +		}if (@{$WVRange}[1] !~/^(@?(\d+|(\d+|~):(\d+)?))?$/){ +			${$Error} = "Invalid Application Warning threshold in ${$WVRange[1]}"; +			return 0; +		} +	} +	 +	# Check Critical thresholds list +	$commas = $Nagios->opts->critical =~ tr/,//;  +	if ($commas !=1){ +		${$Error} = "Invalid Critical list format. One comma is expected."; +		return 0; +	} +	else{ +		$i=0; +		$firstpos=0; +		my $critical=$Nagios->opts->critical; +		while ($critical  =~ /[,]/g) { +			$secondpos=pos $critical ; +			if ($secondpos - $firstpos==1){ +				@{$CVRange}[$i] = "~:"; +			}		 +			else{ +				@{$CVRange}[$i] =substr $Nagios->opts->critical, $firstpos, ($secondpos-$firstpos-1); +			} +			$firstpos=$secondpos; +			$i++ +		} +		if (length($Nagios->opts->critical) - $firstpos==0){#La coma es el ultimo elemento del string +			@{$CVRange}[$i] = "~:"; +		} +		else{ +			@{$CVRange}[$i] = substr $Nagios->opts->critical, $firstpos, (length($Nagios->opts->critical)-$firstpos); +		}		 + +		if (@{$CVRange}[0] !~/^(@?(\d+|(\d+|~):(\d+)?))?$/) { +			${$Error} = "Invalid Process Critical threshold in @{$CVRange}[0]"; +			return 0; +		} +		if (@{$CVRange}[1] !~/^(@?(\d+|(\d+|~):(\d+)?))?$/) { +			${$Error} = "Invalid Application Critical threshold in @{$CVRange}[1]"; +			return 0; +		} +	} +	 +	return 1; +} + + +# Performs whole check:  +# Input: Nagios Plugin object, reference to Plugin output string, Application, referece to WVRange, reference to CVRange +# Output: Plugin output string +# Return value: Plugin return value + +sub PerformCheck() { +	my ($Nagios, $PluginOutput, $WVRange, $CVRange) = @_; +	my $Application; +	my @AppNameSplitted; +	my $ApplicationName; +	my $PsCommand; +	my $PsResult; +	my @PsResultLines; +	my $ProcLine; +	my $ProcPid; +	my $LsofCommand; +	my $LsofResult; +	my $ProcCount = 0; +	my $FDCount = 0; +	my $ProcFDAvg = 0; +	my $PerProcMaxFD = 0; +	my $ProcOKFlag = 0; +	my $ProcWarningFlag = 0; +	my $ProcCriticalFlag = 0; +	my $OKFlag = 0; +	my $WarningFlag = 0; +	my $CriticalFlag = 0; +	my $LastWarningProcFDs = 0; +	my $LastWarningProc = -1; +	my $LastCriticalProcFDs = 0; +	my $LastCriticalProc = -1; +	my $ProcPluginReturnValue = UNKNOWN; +	my $AppPluginReturnValue = UNKNOWN; + 	my $PluginReturnValue = UNKNOWN; + 	my $PerformanceData = ""; +	my $PerfdataUnit = "FDs"; +	 +	$Application = $Nagios->opts->application; +	$PsCommand = "ps -eaf | grep $Application"; +	$PsResult = `$PsCommand`; +	@AppNameSplitted = split(/\//, $Application); +	$ApplicationName = $AppNameSplitted[$#AppNameSplitted]; +	@PsResultLines = split(/\n/, $PsResult); +	if ( $#PsResultLines > 1 ) { +	    foreach my $Proc (split(/\n/, $PsResult)) { +		if ($Proc !~ /check_unix_open_fds/ && $Proc !~ / grep /) { +				$ProcCount += 1; +			    $ProcPid = (split(/\s+/, $Proc))[1]; +			    $LsofCommand = "lsof -p $ProcPid | wc -l"; +			    $LsofResult = `$LsofCommand`; +			    $LsofResult = ($LsofResult > 0 ) ? ($LsofResult - 1) : 0; +			    $FDCount += $LsofResult; +			    if ($LsofResult >= $PerProcMaxFD) { $PerProcMaxFD = $LsofResult; } +			    $ProcPluginReturnValue = $Nagios->check_threshold(check => $LsofResult,warning => @{$WVRange}[0],critical => @{$CVRange}[0]); +			    if ($ProcPluginReturnValue eq OK) { +			    	$ProcOKFlag = 1; +			    } +			    elsif ($ProcPluginReturnValue eq WARNING) { +					$ProcWarningFlag = 1; +					if ($LsofResult >= $LastWarningProcFDs) { +					    $LastWarningProcFDs = $LsofResult; +					    $LastWarningProc = $ProcPid; +					} +			    } +				#if ($LsofResult >= $PCT) { +				elsif ($ProcPluginReturnValue eq CRITICAL) { +				    $ProcCriticalFlag = 1; +				    if ($LsofResult >= $LastCriticalProcFDs) { +						$LastCriticalProcFDs = $LsofResult; +						$LastCriticalProc = $ProcPid; +				    } +				} +		    } +	    } +	    if ($ProcCount) { $ProcFDAvg = int($FDCount / $ProcCount); } +	    $AppPluginReturnValue = $Nagios->check_threshold(check => $FDCount,warning => @{$WVRange}[1],critical => @{$CVRange}[1]); +	    #if ($FDCount >= $TWT) { +	    if ($AppPluginReturnValue eq OK) { $OKFlag = 1; } +	    elsif ($AppPluginReturnValue eq WARNING) { $WarningFlag = 1; } +	    elsif ($AppPluginReturnValue eq CRITICAL) { $CriticalFlag = 1; } +	 +	    # PluginReturnValue and PluginOutput +	    if ($CriticalFlag) { +	    	$PluginReturnValue = CRITICAL; +			${$PluginOutput} .= "$ApplicationName handling $FDCount files (critical threshold set to @{$CVRange}[1])"; +	    } +	    elsif ($WarningFlag) { +	    	$PluginReturnValue = WARNING; +			${$PluginOutput} .= "$ApplicationName handling $FDCount files (warning threshold set to @{$WVRange}[1])"; +	    } +	    elsif ($ProcCriticalFlag) { +	    	$PluginReturnValue = CRITICAL; +			${$PluginOutput} .= "Process ID $LastCriticalProc handling $LastCriticalProcFDs files (critical threshold set to @{$CVRange}[0])"; +	    } +	    elsif ($ProcWarningFlag) { +	    	$PluginReturnValue = WARNING; +			${$PluginOutput} .= "Process ID $LastWarningProc handling $LastWarningProcFDs files (warning threshold set to @{$WVRange}[0])"; +	    } +	    elsif ($OKFlag && $ProcOKFlag) { +	    	$PluginReturnValue = OK; +			${$PluginOutput} .= "$ApplicationName handling $FDCount files"; +	    } +	} +	else { +	    ${$PluginOutput} .= "No existe la aplicacion $ApplicationName"; +	} + +      +	$PerformanceData .= "ProcCount=$ProcCount$PerfdataUnit FDCount=$FDCount$PerfdataUnit ProcFDAvg=$ProcFDAvg$PerfdataUnit PerProcMaxFD=$PerProcMaxFD$PerfdataUnit"; + +	# Output with performance data: +	${$PluginOutput} .= " | $PerformanceData"; + + 	return $PluginReturnValue; +} diff --git a/puppet/modules/site_check_mk/files/agent/plugins/mk_logwatch.1.2.4 b/puppet/modules/site_check_mk/files/agent/plugins/mk_logwatch.1.2.4 new file mode 100755 index 00000000..3dbca322 --- /dev/null +++ b/puppet/modules/site_check_mk/files/agent/plugins/mk_logwatch.1.2.4 @@ -0,0 +1,374 @@ +#!/usr/bin/python +# -*- encoding: utf-8; py-indent-offset: 4 -*- +# +------------------------------------------------------------------+ +# |             ____ _               _        __  __ _  __           | +# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           | +# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            | +# |           | |___| | | |  __/ (__|   <    | |  | | . \            | +# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           | +# |                                                                  | +# | Copyright Mathias Kettner 2010             mk@mathias-kettner.de | +# +------------------------------------------------------------------+ +# +# This file is part of Check_MK. +# The official homepage is at http://mathias-kettner.de/check_mk. +# +# check_mk is free software;  you can redistribute it and/or modify it +# under the  terms of the  GNU General Public License  as published by +# the Free Software Foundation in version 2.  check_mk is  distributed +# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with- +# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A +# PARTICULAR PURPOSE. See the  GNU General Public License for more de- +# ails.  You should have  received  a copy of the  GNU  General Public +# License along with GNU Make; see the file  COPYING.  If  not,  write +# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor, +# Boston, MA 02110-1301 USA. + +# Call with -d for debug mode: colored output, no saving of status + +import sys, os, re, time +import glob + +if '-d' in sys.argv[1:] or '--debug' in sys.argv[1:]: +    tty_red     = '\033[1;31m' +    tty_green   = '\033[1;32m' +    tty_yellow  = '\033[1;33m' +    tty_blue    = '\033[1;34m' +    tty_normal  = '\033[0m' +    debug = True +else: +    tty_red     = '' +    tty_green   = '' +    tty_yellow  = '' +    tty_blue    = '' +    tty_normal  = '' +    debug = False + +# The configuration file and status file are searched +# in the directory named by the environment variable +# LOGWATCH_DIR. If that is not set, MK_CONFDIR is used. +# If that is not set either, the current directory ist +# used. +logwatch_dir = os.getenv("LOGWATCH_DIR") +if not logwatch_dir: +    logwatch_dir = os.getenv("MK_CONFDIR") +    if not logwatch_dir: +        logwatch_dir = "." + +print "<<<logwatch>>>" + +config_filename = logwatch_dir + "/logwatch.cfg" +status_filename = logwatch_dir + "/logwatch.state" +config_dir      = logwatch_dir + "/logwatch.d/*.cfg" + +def is_not_comment(line): +    if line.lstrip().startswith('#') or \ +       line.strip() == '': +        return False +    return True + +def parse_filenames(line): +    return line.split() + +def parse_pattern(level, pattern): +    if level not in [ 'C', 'W', 'I', 'O' ]: +        raise(Exception("Invalid pattern line '%s'" % line)) +    try: +        compiled = re.compile(pattern) +    except: +        raise(Exception("Invalid regular expression in line '%s'" % line)) +    return (level, compiled) + +def read_config(): +    config_lines = [ line.rstrip() for line in filter(is_not_comment, file(config_filename).readlines()) ] +    # Add config from a logwatch.d folder +    for config_file in glob.glob(config_dir): +        config_lines += [ line.rstrip() for line in filter(is_not_comment, file(config_file).readlines()) ] + +    have_filenames = False +    config = [] + +    for line in config_lines: +        rewrite = False +        if line[0].isspace(): # pattern line +            if not have_filenames: +                raise Exception("Missing logfile names") +            level, pattern = line.split(None, 1) +            if level == 'A': +                cont_list.append(parse_cont_pattern(pattern)) +            elif level == 'R': +                rewrite_list.append(pattern) +            else: +                level, compiled = parse_pattern(level, pattern) +                cont_list = [] # List of continuation patterns +                rewrite_list = [] # List of rewrite patterns +                patterns.append((level, compiled, cont_list, rewrite_list)) +        else: # filename line +            patterns = [] +            config.append((parse_filenames(line), patterns)) +            have_filenames = True +    return config + +def parse_cont_pattern(pattern): +    try: +        return int(pattern) +    except: +        try: +            return re.compile(pattern) +        except: +            if debug: +                raise +            raise Exception("Invalid regular expression in line '%s'" % pattern)  + +# structure of statusfile +# # LOGFILE         OFFSET    INODE +# /var/log/messages|7767698|32455445 +# /var/test/x12134.log|12345|32444355 +def read_status(): +    if debug: +        return {} + +    status = {} +    for line in file(status_filename): +        # TODO: Remove variants with spaces. rsplit is +        # not portable. split fails if logfilename contains +        # spaces +        inode = -1 +        try: +            parts = line.split('|') +            filename = parts[0] +            offset = parts[1] +            if len(parts) >= 3: +                inode = parts[2] + +        except: +            try: +                filename, offset = line.rsplit(None, 1) +            except: +                filename, offset = line.split(None, 1) +        status[filename] = int(offset), int(inode) +    return status + +def save_status(status): +    f = file(status_filename, "w") +    for filename, (offset, inode) in status.items(): +        f.write("%s|%d|%d\n" % (filename, offset, inode)) + +pushed_back_line = None +def next_line(f): +    global pushed_back_line +    if pushed_back_line != None: +        line = pushed_back_line +        pushed_back_line = None +        return line +    else: +        try: +            line = f.next() +            return line +        except: +            return None + + +def process_logfile(logfile, patterns): +    global pushed_back_line + +    # Look at which file offset we have finished scanning +    # the logfile last time. If we have never seen this file +    # before, we set the offset to -1 +    offset, prev_inode = status.get(logfile, (-1, -1)) +    try: +        fl = os.open(logfile, os.O_RDONLY) +        inode = os.fstat(fl)[1] # 1 = st_ino +    except: +        if debug: +            raise +        print "[[[%s:cannotopen]]]" % logfile +        return + +    print "[[[%s]]]" % logfile + +    # Seek to the current end in order to determine file size +    current_end = os.lseek(fl, 0, 2) # os.SEEK_END not available in Python 2.4 +    status[logfile] = current_end, inode +         +    # If we have never seen this file before, we just set the +    # current pointer to the file end. We do not want to make +    # a fuss about ancient log messages... +    if offset == -1: +	if not debug: +            return +    	else: +	    offset = 0 +    + +    # If the inode of the logfile has changed it has appearently +    # been started from new (logfile rotation). At least we must +    # assume that. In some rare cases (restore of a backup, etc) +    # we are wrong and resend old log messages +    if prev_inode >= 0 and inode != prev_inode: +        offset = 0 + +    # Our previously stored offset is the current end -> +    # no new lines in this file +    if offset == current_end: +        return # nothing new + +    # If our offset is beyond the current end, the logfile has been +    # truncated or wrapped while keeping the same inode. We assume +    # that it contains all new data in that case and restart from +    # offset 0. +    if offset > current_end: +        offset = 0 + +    # now seek to offset where interesting data begins +    os.lseek(fl, offset, 0) # os.SEEK_SET not available in Python 2.4 +    f = os.fdopen(fl) +    worst = -1 +    outputtxt = "" +    lines_parsed = 0 +    start_time = time.time() + +    while True: +        line = next_line(f) +        if line == None: +            break # End of file + +        lines_parsed += 1 +        # Check if maximum number of new log messages is exceeded +        if opt_maxlines != None and lines_parsed > opt_maxlines: +            outputtxt += "%s Maximum number (%d) of new log messages exceeded.\n" % ( +               opt_overflow, opt_maxlines) +            worst = max(worst, opt_overflow_level) +            os.lseek(fl, 0, 2) # Seek to end of file, skip all other messages +            break + +        # Check if maximum processing time (per file) is exceeded. Check only +        # every 100'th line in order to save system calls +        if opt_maxtime != None and lines_parsed % 100 == 10 \ +            and time.time() - start_time > opt_maxtime: +            outputtxt += "%s Maximum parsing time (%.1f sec) of this log file exceeded.\n" % ( +               opt_overflow, opt_maxtime) +            worst = max(worst, opt_overflow_level) +            os.lseek(fl, 0, 2) # Seek to end of file, skip all other messages +            break + +        level = "." +        for lev, pattern, cont_patterns, replacements in patterns: +            matches = pattern.search(line[:-1]) +            if matches: +                level = lev +                levelint = {'C': 2, 'W': 1, 'O': 0, 'I': -1, '.': -1}[lev] +                worst = max(levelint, worst) + +                # Check for continuation lines +                for cont_pattern in cont_patterns: +                    if type(cont_pattern) == int: # add that many lines +                        for x in range(cont_pattern): +                            cont_line = next_line(f) +                            if cont_line == None: # end of file +                                break +                            line = line[:-1] + "\1" + cont_line  + +                    else: # pattern is regex +                        while True: +                            cont_line = next_line(f) +                            if cont_line == None: # end of file +                                break +                            elif cont_pattern.search(cont_line[:-1]): +                                line = line[:-1] + "\1" + cont_line  +                            else: +                                pushed_back_line = cont_line # sorry for stealing this line +                                break + +                # Replacement +                for replace in replacements: +                    line = replace.replace('\\0', line) + "\n" +                    for nr, group in enumerate(matches.groups()): +                        line = line.replace('\\%d' % (nr+1), group) + +                break # matching rule found and executed + +        color = {'C': tty_red, 'W': tty_yellow, 'O': tty_green, 'I': tty_blue, '.': ''}[level] +        if debug: +            line = line.replace("\1", "\nCONT:") +        if level == "I": +            level = "." +        if opt_nocontext and level == '.': +            continue +        outputtxt += "%s%s %s%s\n" % (color, level, line[:-1], tty_normal) + +    new_offset = os.lseek(fl, 0, 1) # os.SEEK_CUR not available in Python 2.4 +    status[logfile] = new_offset, inode + +    # output all lines if at least one warning, error or ok has been found +    if worst > -1: +        sys.stdout.write(outputtxt) +        sys.stdout.flush() + +try: +    config = read_config() +except Exception, e: +    if debug: +        raise +    print "CANNOT READ CONFIG FILE: %s" % e +    sys.exit(1) + +# Simply ignore errors in the status file.  In case of a corrupted status file we simply begin +# with an empty status. That keeps the monitoring up and running - even if we might loose a +# message in the extreme case of a corrupted status file. +try: +    status = read_status() +except Exception, e: +    status = {} + + +# The filename line may contain options like 'maxlines=100' or 'maxtime=10' +for filenames, patterns in config: +    # Initialize options with default values +    opt_maxlines = None +    opt_maxtime = None +    opt_regex = None +    opt_overflow = 'C' +    opt_overflow_level = 2 +    opt_nocontext = False +    try: +        options = [ o.split('=', 1) for o in filenames if '=' in o ] +        for key, value in options: +            if key == 'maxlines': +                opt_maxlines = int(value) +            elif key == 'maxtime': +                opt_maxtime = float(value) +            elif key == 'overflow': +                if value not in [ 'C', 'I', 'W', 'O' ]: +                    raise Exception("Invalid value %s for overflow. Allowed are C, I, O and W" % value) +                opt_overflow = value +                opt_overflow_level = {'C':2, 'W':1, 'O':0, 'I':0}[value] +            elif key == 'regex': +                opt_regex = re.compile(value) +            elif key == 'iregex': +                opt_regex = re.compile(value, re.I) +            elif key == 'nocontext': +                opt_nocontext = True +            else: +                raise Exception("Invalid option %s" % key) +    except Exception, e: +        if debug: +            raise +        print "INVALID CONFIGURATION: %s" % e +        sys.exit(1) + + +    for glob in filenames: +        if '=' in glob: +            continue +        logfiles = [ l.strip() for l in os.popen("ls %s 2>/dev/null" % glob).readlines() ] +        if opt_regex: +            logfiles = [ f for f in logfiles if opt_regex.search(f) ] +        if len(logfiles) == 0: +            print '[[[%s:missing]]]' % glob +        else: +            for logfile in logfiles: +                process_logfile(logfile, patterns) + +if not debug: +    save_status(status) diff --git a/puppet/modules/site_check_mk/files/extra_service_conf.mk b/puppet/modules/site_check_mk/files/extra_service_conf.mk new file mode 100644 index 00000000..c7120a96 --- /dev/null +++ b/puppet/modules/site_check_mk/files/extra_service_conf.mk @@ -0,0 +1,14 @@ +# retry 3 times before setting a service into a hard state +# and send out notification +extra_service_conf["max_check_attempts"] = [ +  ("4", ALL_HOSTS , ALL_SERVICES ) +] + +# +# run check_mk_agent every 4 minutes if it terminates successfully. +# see https://leap.se/code/issues/6539 for the rationale +# +extra_service_conf["normal_check_interval"] = [ +  ("4", ALL_HOSTS , "Check_MK" ) +] + diff --git a/puppet/modules/site_check_mk/files/ignored_services.mk b/puppet/modules/site_check_mk/files/ignored_services.mk new file mode 100644 index 00000000..35dc4433 --- /dev/null +++ b/puppet/modules/site_check_mk/files/ignored_services.mk @@ -0,0 +1,3 @@ +ignored_services = [ +  ( ALL_HOSTS, [ "NTP Time" ] ) +] diff --git a/puppet/modules/site_check_mk/manifests/agent.pp b/puppet/modules/site_check_mk/manifests/agent.pp new file mode 100644 index 00000000..b95d5d64 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent.pp @@ -0,0 +1,35 @@ +# installs check-mk agent +class site_check_mk::agent { + +  $ssh_hash = hiera('ssh') +  $pubkey   = $ssh_hash['authorized_keys']['monitor']['key'] +  $type     = $ssh_hash['authorized_keys']['monitor']['type'] + + +  # /usr/bin/mk-job depends on /usr/bin/time +  ensure_packages('time') + +  class { 'site_apt::preferences::check_mk': } -> + +  class { 'check_mk::agent': +    agent_package_name          => 'check-mk-agent', +    agent_logwatch_package_name => 'check-mk-agent-logwatch', +    method                      => 'ssh', +    authdir                     => '/root/.ssh', +    authfile                    => 'authorized_keys', +    register_agent              => false, +    require                     => Package['time'] +  } -> + +  class { 'site_check_mk::agent::mrpe': } -> +  class { 'site_check_mk::agent::logwatch': } -> + +  file { +    [ '/srv/leap/nagios', '/srv/leap/nagios/plugins' ]: +      ensure  => directory; +    '/usr/lib/check_mk_agent/local/run_node_tests.sh': +      source => 'puppet:///modules/site_check_mk/agent/local_checks/all_hosts/run_node_tests.sh', +      mode   => '0755'; +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/couchdb.pp b/puppet/modules/site_check_mk/manifests/agent/couchdb.pp new file mode 100644 index 00000000..1554fd3c --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/couchdb.pp @@ -0,0 +1,34 @@ +# configure logwatch and nagios checks for couchdb (both bigcouch and plain +# couchdb installations) +class site_check_mk::agent::couchdb { + +  concat::fragment { 'syslog_couchdb': +    source  => 'puppet:///modules/site_check_mk/agent/logwatch/syslog/couchdb.cfg', +    target  => '/etc/check_mk/logwatch.d/syslog.cfg', +    order   => '02'; +  } + +  # check different couchdb stats +  file { '/usr/lib/check_mk_agent/local/leap_couch_stats.sh': +    source  => 'puppet:///modules/site_check_mk/agent/local_checks/couchdb/leap_couch_stats.sh', +    mode    => '0755', +    require => Package['check_mk-agent'] +  } + +  # check open files for bigcouch proc +  include site_check_mk::agent::package::perl_plugin +  file { '/srv/leap/nagios/plugins/check_unix_open_fds.pl': +    source => 'puppet:///modules/site_check_mk/agent/nagios_plugins/check_unix_open_fds.pl', +    mode   => '0755' +  } +  augeas { +    'Couchdb_open_files': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => [ +        'rm /files/etc/check_mk/mrpe.cfg/Couchdb_open_files', +        'set Couchdb_open_files \'/srv/leap/nagios/plugins/check_unix_open_fds.pl -a beam -w 28672,28672 -c 30720,30720\'' ], +      require => File['/etc/check_mk/mrpe.cfg']; +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/couchdb/bigcouch.pp b/puppet/modules/site_check_mk/manifests/agent/couchdb/bigcouch.pp new file mode 100644 index 00000000..82c3ac72 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/couchdb/bigcouch.pp @@ -0,0 +1,49 @@ +# configure logwatch and nagios checks for bigcouch +class site_check_mk::agent::couchdb::bigcouch { + +  # watch bigcouch logs +  # currently disabled because bigcouch is too noisy +  # see https://leap.se/code/issues/7375 for more details +  # and site_config::remove_files for removing leftovers +  #file { '/etc/check_mk/logwatch.d/bigcouch.cfg': +  #  source => 'puppet:///modules/site_check_mk/agent/logwatch/bigcouch.cfg', +  #} + +  # check syslog msg from: +  # - empd +  # - /usr/local/bin/couch-doc-update +  concat::fragment { 'syslog_bigcouch': +    source  => 'puppet:///modules/site_check_mk/agent/logwatch/syslog/bigcouch.cfg', +    target  => '/etc/check_mk/logwatch.d/syslog.cfg', +    order   => '02'; +  } + +  # check bigcouch processes +  augeas { +    'Bigcouch_epmd_procs': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => [ +        'rm /files/etc/check_mk/mrpe.cfg/Bigcouch_epmd_procs', +        'set Bigcouch_epmd_procs \'/usr/lib/nagios/plugins/check_procs -w 1:1 -c 1:1 -a /opt/bigcouch/erts-5.9.1/bin/epmd\'' ], +      require => File['/etc/check_mk/mrpe.cfg']; +    'Bigcouch_beam_procs': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => [ +        'rm /files/etc/check_mk/mrpe.cfg/Bigcouch_beam_procs', +        'set Bigcouch_beam_procs \'/usr/lib/nagios/plugins/check_procs -w 1:1 -c 1:1 -a /opt/bigcouch/erts-5.9.1/bin/beam\'' ], +      require => File['/etc/check_mk/mrpe.cfg']; +  } + +  augeas { +    'Bigcouch_open_files': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => [ +        'rm /files/etc/check_mk/mrpe.cfg/Bigcouch_open_files', +        'set Bigcouch_open_files \'/srv/leap/nagios/plugins/check_unix_open_fds.pl -a beam -w 28672,28672 -c 30720,30720\'' ], +      require => File['/etc/check_mk/mrpe.cfg']; +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/couchdb/plain.pp b/puppet/modules/site_check_mk/manifests/agent/couchdb/plain.pp new file mode 100644 index 00000000..3ec2267b --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/couchdb/plain.pp @@ -0,0 +1,23 @@ +# configure logwatch and nagios checks for plain single couchdb master +class site_check_mk::agent::couchdb::plain { + +  # remove bigcouch leftovers +  augeas { +    'Bigcouch_epmd_procs': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => 'rm /files/etc/check_mk/mrpe.cfg/Bigcouch_epmd_procs', +      require => File['/etc/check_mk/mrpe.cfg']; +    'Bigcouch_beam_procs': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => 'rm /files/etc/check_mk/mrpe.cfg/Bigcouch_beam_procs', +      require => File['/etc/check_mk/mrpe.cfg']; +    'Bigcouch_open_files': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => 'rm /files/etc/check_mk/mrpe.cfg/Bigcouch_open_files', +      require => File['/etc/check_mk/mrpe.cfg']; +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/haproxy.pp b/puppet/modules/site_check_mk/manifests/agent/haproxy.pp new file mode 100644 index 00000000..6d52efba --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/haproxy.pp @@ -0,0 +1,15 @@ +class site_check_mk::agent::haproxy { + +  include site_check_mk::agent::package::nagios_plugins_contrib + +  # local nagios plugin checks via mrpe +  augeas { 'haproxy': +    incl    => '/etc/check_mk/mrpe.cfg', +    lens    => 'Spacevars.lns', +    changes => [ +      'rm /files/etc/check_mk/mrpe.cfg/Haproxy', +      'set Haproxy \'/usr/lib/nagios/plugins/check_haproxy -u "http://localhost:8000/haproxy;csv"\'' ], +    require => File['/etc/check_mk/mrpe.cfg']; +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/haveged.pp b/puppet/modules/site_check_mk/manifests/agent/haveged.pp new file mode 100644 index 00000000..cacbea8c --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/haveged.pp @@ -0,0 +1,15 @@ +class site_check_mk::agent::haveged { + +# check haveged process +  augeas { +    'haveged_proc': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => [ +        'rm /files/etc/check_mk/mrpe.cfg/haveged_proc', +        'set haveged_proc \'/usr/lib/nagios/plugins/check_procs -w 1:1 -c 1:1 -a /usr/sbin/haveged\'' ], +      require => File['/etc/check_mk/mrpe.cfg']; + +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/logwatch.pp b/puppet/modules/site_check_mk/manifests/agent/logwatch.pp new file mode 100644 index 00000000..423cace2 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/logwatch.pp @@ -0,0 +1,36 @@ +class site_check_mk::agent::logwatch { +  # Deploy mk_logwatch 1.2.4 so we can split the config +  # into multiple config files in /etc/check_mk/logwatch.d +  # see https://leap.se/code/issues/5135 + +  file { '/usr/lib/check_mk_agent/plugins/mk_logwatch': +    source  => 'puppet:///modules/site_check_mk/agent/plugins/mk_logwatch.1.2.4', +    mode    => '0755', +    require => Package['check-mk-agent-logwatch'] +  } + +  # only config files that watch a distinct logfile should go in logwatch.d/ +  file { '/etc/check_mk/logwatch.d': +    ensure  => directory, +    recurse => true, +    purge   => true, +    require => Package['check-mk-agent-logwatch'] +  } + +  # service that share a common logfile (i.e. /var/log/syslog) need to get +  # concanated in one file, otherwise the last file sourced will override +  # the config before +  # see mk_logwatch: "logwatch.cfg overwrites config files in logwatch.d", +  # https://leap.se/code/issues/5155 + +  # first, we need to deploy a custom logwatch.cfg that doesn't include +  # a section about /var/log/syslog + +  file { '/etc/check_mk/logwatch.cfg': +    source  => 'puppet:///modules/site_check_mk/agent/logwatch/logwatch.cfg', +    require => Package['check_mk-agent-logwatch'] +  } + +  include concat::setup +  include site_check_mk::agent::logwatch::syslog +} diff --git a/puppet/modules/site_check_mk/manifests/agent/logwatch/syslog.pp b/puppet/modules/site_check_mk/manifests/agent/logwatch/syslog.pp new file mode 100644 index 00000000..c927780d --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/logwatch/syslog.pp @@ -0,0 +1,18 @@ +class site_check_mk::agent::logwatch::syslog { + +  concat { '/etc/check_mk/logwatch.d/syslog.cfg': +    warn    => true +  } + +  concat::fragment { 'syslog_header': +    source => 'puppet:///modules/site_check_mk/agent/logwatch/syslog_header.cfg', +    target => '/etc/check_mk/logwatch.d/syslog.cfg', +    order  => '01'; +  } +  concat::fragment { 'syslog_tail': +    source => 'puppet:///modules/site_check_mk/agent/logwatch/syslog_tail.cfg', +    target => '/etc/check_mk/logwatch.d/syslog.cfg', +    order  => '99'; +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/mrpe.pp b/puppet/modules/site_check_mk/manifests/agent/mrpe.pp new file mode 100644 index 00000000..5e1f087a --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/mrpe.pp @@ -0,0 +1,24 @@ +class site_check_mk::agent::mrpe { +  # check_mk can use standard nagios plugins using +  # a wrapper called mrpe +  # see http://mathias-kettner.de/checkmk_mrpe.html + +  package { 'nagios-plugins-basic': +    ensure => latest, +  } + +  file { '/etc/check_mk/mrpe.cfg': +    ensure  => present, +    require => Package['check-mk-agent'] +  } -> + +  augeas { +    'Apt': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => [ +        'rm /files/etc/check_mk/mrpe.cfg/APT', +        'set APT \'/usr/lib/nagios/plugins/check_apt\'' ]; +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/mx.pp b/puppet/modules/site_check_mk/manifests/agent/mx.pp new file mode 100644 index 00000000..20cbcade --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/mx.pp @@ -0,0 +1,27 @@ +# check check_mk agent checks for mx service +class site_check_mk::agent::mx { + +  # watch logs +  file { '/etc/check_mk/logwatch.d/leap_mx.cfg': +    source => 'puppet:///modules/site_check_mk/agent/logwatch/leap_mx.cfg', +  } + +  # local nagios plugin checks via mrpe +  # removed because leap_cli integrates a check for running mx procs already, +  # which is also integrated into nagios (called "Mx/Are_MX_daemons_running") +  augeas { +    'Leap_MX_Procs': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => 'rm /files/etc/check_mk/mrpe.cfg/Leap_MX_Procs', +      require => File['/etc/check_mk/mrpe.cfg']; +  } + +  # check stale files in queue dir +  file { '/usr/lib/check_mk_agent/local/check_leap_mx.sh': +    source  => 'puppet:///modules/site_check_mk/agent/local_checks/mx/check_leap_mx.sh', +    mode    => '0755', +    require => Package['check_mk-agent'] +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/openvpn.pp b/puppet/modules/site_check_mk/manifests/agent/openvpn.pp new file mode 100644 index 00000000..0596a497 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/openvpn.pp @@ -0,0 +1,10 @@ +class site_check_mk::agent::openvpn { + +  # check syslog +  concat::fragment { 'syslog_openpvn': +    source  => 'puppet:///modules/site_check_mk/agent/logwatch/openvpn.cfg', +    target  => '/etc/check_mk/logwatch.d/syslog.cfg', +    order   => '02'; +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/package/nagios_plugins_contrib.pp b/puppet/modules/site_check_mk/manifests/agent/package/nagios_plugins_contrib.pp new file mode 100644 index 00000000..95a60d17 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/package/nagios_plugins_contrib.pp @@ -0,0 +1,5 @@ +class site_check_mk::agent::package::nagios_plugins_contrib  { +  package { 'nagios-plugins-contrib': +    ensure => installed, +  } +} diff --git a/puppet/modules/site_check_mk/manifests/agent/package/perl_plugin.pp b/puppet/modules/site_check_mk/manifests/agent/package/perl_plugin.pp new file mode 100644 index 00000000..4feda375 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/package/perl_plugin.pp @@ -0,0 +1,5 @@ +class site_check_mk::agent::package::perl_plugin  { +  package { 'libnagios-plugin-perl': +    ensure => installed, +  } +} diff --git a/puppet/modules/site_check_mk/manifests/agent/soledad.pp b/puppet/modules/site_check_mk/manifests/agent/soledad.pp new file mode 100644 index 00000000..f4a3f3a6 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/soledad.pp @@ -0,0 +1,17 @@ +class site_check_mk::agent::soledad { + +  file { '/etc/check_mk/logwatch.d/soledad.cfg': +    source => 'puppet:///modules/site_check_mk/agent/logwatch/soledad.cfg', +  } + +  # local nagios plugin checks via mrpe + +  augeas { 'Soledad_Procs': +    incl    => '/etc/check_mk/mrpe.cfg', +    lens    => 'Spacevars.lns', +    changes => [ +      'rm /files/etc/check_mk/mrpe.cfg/Soledad_Procs', +      'set Soledad_Procs \'/usr/lib/nagios/plugins/check_procs -w 1:1 -c 1:1 -a "/usr/bin/python /usr/bin/twistd --uid=soledad --gid=soledad --pidfile=/var/run/soledad.pid --logfile=/var/log/soledad.log web --wsgi=leap.soledad.server.application --port=ssl:2323:privateKey=/etc/x509/keys/leap.key:certKey=/etc/x509/certs/leap.crt:sslmethod=SSLv23_METHOD"\'' ], +    require => File['/etc/check_mk/mrpe.cfg']; +  } +} diff --git a/puppet/modules/site_check_mk/manifests/agent/stunnel.pp b/puppet/modules/site_check_mk/manifests/agent/stunnel.pp new file mode 100644 index 00000000..7f765771 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/stunnel.pp @@ -0,0 +1,9 @@ +class site_check_mk::agent::stunnel { + +  concat::fragment { 'syslog_stunnel': +    source  => 'puppet:///modules/site_check_mk/agent/logwatch/stunnel.cfg', +    target  => '/etc/check_mk/logwatch.d/syslog.cfg', +    order   => '02'; +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/agent/webapp.pp b/puppet/modules/site_check_mk/manifests/agent/webapp.pp new file mode 100644 index 00000000..9bf3b197 --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/agent/webapp.pp @@ -0,0 +1,15 @@ +class site_check_mk::agent::webapp { + +  # remove leftovers of webapp python checks +  file { +    [ '/usr/lib/check_mk_agent/local/nagios-webapp_login.py', +      '/usr/lib/check_mk_agent/local/soledad_sync.py' ]: +    ensure  => absent +  } + +  # watch logs +  file { '/etc/check_mk/logwatch.d/webapp.cfg': +    source => 'puppet:///modules/site_check_mk/agent/logwatch/webapp.cfg', +  } + +} diff --git a/puppet/modules/site_check_mk/manifests/server.pp b/puppet/modules/site_check_mk/manifests/server.pp new file mode 100644 index 00000000..7ff9eb4a --- /dev/null +++ b/puppet/modules/site_check_mk/manifests/server.pp @@ -0,0 +1,103 @@ +# setup check_mk on the monitoring server +class site_check_mk::server { + +  $ssh_hash = hiera('ssh') +  $pubkey   = $ssh_hash['authorized_keys']['monitor']['key'] +  $type     = $ssh_hash['authorized_keys']['monitor']['type'] +  $seckey   = $ssh_hash['monitor']['private_key'] + +  $nagios_hiera     = hiera_hash('nagios') +  $hosts            = $nagios_hiera['hosts'] + +  $all_hosts        = inline_template ('<% @hosts.keys.sort.each do |key| -%><% if @hosts[key]["environment"] != "disabled" %>"<%= @hosts[key]["domain_internal"] %>", <% end -%><% end -%>') +  $domains_internal = $nagios_hiera['domains_internal'] +  $environments     = $nagios_hiera['environments'] + +  package { 'check-mk-server': +    ensure => installed, +  } + +  # we don't use check-mk-multisite, and the jessie version +  # of this config file breaks with apache 2.4 +  # until https://gitlab.com/shared-puppet-modules-group/apache/issues/11 +  # is not fixed, we need to use a generic file type here +  #apache::config::global { 'check-mk-multisite.conf': +  #  ensure => absent +  #} + +  file { '/etc/apache2/conf-enabled/check-mk-multisite.conf': +    ensure  => absent, +    require => Package['check-mk-server']; +  } + +  # override paths to use the system check_mk rather than OMD +  class { 'check_mk::config': +    site                      => '', +    etc_dir                   => '/etc', +    nagios_subdir             => 'nagios3', +    bin_dir                   => '/usr/bin', +    host_groups               => undef, +    use_storedconfigs         => false, +    inventory_only_on_changes => false, +    require                   => Package['check-mk-server'] +  } + +  Exec['check_mk-refresh'] -> +    Exec['check_mk-refresh-inventory-daily'] -> +      Exec['check_mk-reload'] -> +        Service['nagios'] + +  file { +    '/etc/check_mk/conf.d/use_ssh.mk': +      content => template('site_check_mk/use_ssh.mk'), +      notify  => Exec['check_mk-refresh'], +      require => Package['check-mk-server']; +    '/etc/check_mk/conf.d/hostgroups.mk': +      content => template('site_check_mk/hostgroups.mk'), +      notify  => Exec['check_mk-refresh'], +      require => Package['check-mk-server']; +    '/etc/check_mk/conf.d/host_contactgroups.mk': +      content => template('site_check_mk/host_contactgroups.mk'), +      notify  => Exec['check_mk-refresh'], +      require => Package['check-mk-server']; +    '/etc/check_mk/conf.d/ignored_services.mk': +      source  => 'puppet:///modules/site_check_mk/ignored_services.mk', +      notify  => Exec['check_mk-refresh'], +      require => Package['check-mk-server']; +    '/etc/check_mk/conf.d/extra_service_conf.mk': +      source  => 'puppet:///modules/site_check_mk/extra_service_conf.mk', +      notify  => Exec['check_mk-refresh'], +      require => Package['check-mk-server']; +    '/etc/check_mk/conf.d/extra_host_conf.mk': +      content => template('site_check_mk/extra_host_conf.mk'), +      notify  => Exec['check_mk-refresh'], +      require => Package['check-mk-server']; + +    '/etc/check_mk/all_hosts_static': +      content => $all_hosts, +      notify  => Exec['check_mk-refresh'], +      require => Package['check-mk-server']; + +    '/etc/check_mk/.ssh': +      ensure  => directory, +      require => Package['check-mk-server']; +    '/etc/check_mk/.ssh/id_rsa': +      content => $seckey, +      owner   => 'nagios', +      mode    => '0600', +      require => Package['check-mk-server']; +    '/etc/check_mk/.ssh/id_rsa.pub': +      content => "${type} ${pubkey} monitor", +      owner   => 'nagios', +      mode    => '0644', +      require => Package['check-mk-server']; + +    # check_icmp must be suid root or called by sudo +    # see https://leap.se/code/issues/5171 +    '/usr/lib/nagios/plugins/check_icmp': +      mode    => '4755', +      require => Package['nagios-plugins-basic']; +  } + +  include check_mk::agent::local_checks +} diff --git a/puppet/modules/site_check_mk/templates/extra_host_conf.mk b/puppet/modules/site_check_mk/templates/extra_host_conf.mk new file mode 100644 index 00000000..bc27b514 --- /dev/null +++ b/puppet/modules/site_check_mk/templates/extra_host_conf.mk @@ -0,0 +1,13 @@ +# retry 3 times before setting a host into a hard state +# and send out notification +extra_host_conf["max_check_attempts"] = [ +  ("4", ALL_HOSTS ) +] + +# Use hostnames as alias so notification mail subjects +# are more readable and not so long. Alias defaults to +# the fqdn of a host is not changed. +extra_host_conf["alias"] = [ +<% @hosts.keys.sort.each do |key| -%>  ( "<%= key.strip %>", ["<%= @hosts[key]['domain_internal']%>"]), +<% end -%> +] diff --git a/puppet/modules/site_check_mk/templates/host_contactgroups.mk b/puppet/modules/site_check_mk/templates/host_contactgroups.mk new file mode 100644 index 00000000..6a534967 --- /dev/null +++ b/puppet/modules/site_check_mk/templates/host_contactgroups.mk @@ -0,0 +1,17 @@ +<% +  contact_groups = [] +  @environments.keys.sort.each do |env_name| +    hosts = "" +    @nagios_hosts.keys.sort.each do |hostname| +      hostdata = @nagios_hosts[hostname] +      domain_internal = hostdata['domain_internal'] +      if hostdata['environment'] == env_name +        hosts << '"' + domain_internal + '", ' +      end +    end +    contact_groups << '  ( "%s", [%s] )' % [env_name, hosts] +  end +%> +host_contactgroups = [ +<%= contact_groups.join(",\n") %> +] diff --git a/puppet/modules/site_check_mk/templates/hostgroups.mk b/puppet/modules/site_check_mk/templates/hostgroups.mk new file mode 100644 index 00000000..7158dcd1 --- /dev/null +++ b/puppet/modules/site_check_mk/templates/hostgroups.mk @@ -0,0 +1,17 @@ +<% +  host_groups = [] +  @environments.keys.sort.each do |env_name| +    hosts = "" +    @nagios_hosts.keys.sort.each do |hostname| +      hostdata = @nagios_hosts[hostname] +      domain_internal = hostdata['domain_internal'] +      if hostdata['environment'] == env_name +        hosts << '"' + domain_internal + '", ' +      end +    end +    host_groups << '  ( "%s", [%s] )' % [env_name, hosts] +  end +%> +host_groups = [ +<%= host_groups.join(",\n") %> +] diff --git a/puppet/modules/site_check_mk/templates/use_ssh.mk b/puppet/modules/site_check_mk/templates/use_ssh.mk new file mode 100644 index 00000000..55269536 --- /dev/null +++ b/puppet/modules/site_check_mk/templates/use_ssh.mk @@ -0,0 +1,6 @@ +# http://mathias-kettner.de/checkmk_datasource_programs.html +datasource_programs = [ +<% @nagios_hosts.sort.each do |name,config| %> + ( "ssh -l root -i /etc/check_mk/.ssh/id_rsa -p <%=config['ssh_port']%> <%=config['domain_internal']%> check_mk_agent", [ "<%=config['domain_internal']%>" ], ),<%- end -%> + +] diff --git a/puppet/modules/site_config/files/xterm-title.sh b/puppet/modules/site_config/files/xterm-title.sh new file mode 100644 index 00000000..3cff0e3a --- /dev/null +++ b/puppet/modules/site_config/files/xterm-title.sh @@ -0,0 +1,8 @@ +# If this is an xterm set the title to user@host:dir +case "$TERM" in +xterm*|rxvt*) +    PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"' +    ;; +*) +    ;; +esac diff --git a/puppet/modules/site_config/lib/facter/dhcp_enabled.rb b/puppet/modules/site_config/lib/facter/dhcp_enabled.rb new file mode 100644 index 00000000..33220da3 --- /dev/null +++ b/puppet/modules/site_config/lib/facter/dhcp_enabled.rb @@ -0,0 +1,22 @@ +require 'facter' +def dhcp_enabled?(ifs, recurse=true) +  dhcp = false +  included_ifs = [] +  if FileTest.exists?(ifs) +    File.open(ifs) do |file| +      dhcp = file.enum_for(:each_line).any? do |line| +        if recurse && line =~ /^\s*source\s+([^\s]+)/ +          included_ifs += Dir.glob($1) +        end +        line =~ /inet\s+dhcp/ +      end +    end +  end +  dhcp || included_ifs.any? { |ifs| dhcp_enabled?(ifs, false) } +end +Facter.add(:dhcp_enabled) do +  confine :osfamily => 'Debian' +  setcode do +    dhcp_enabled?('/etc/network/interfaces') +  end +end diff --git a/puppet/modules/site_config/lib/facter/ip_interface.rb b/puppet/modules/site_config/lib/facter/ip_interface.rb new file mode 100644 index 00000000..45764bfc --- /dev/null +++ b/puppet/modules/site_config/lib/facter/ip_interface.rb @@ -0,0 +1,13 @@ +require 'facter/util/ip' + +Facter::Util::IP.get_interfaces.each do |interface| +  ip = Facter.value("ipaddress_#{interface}") +  if ip != nil +    Facter.add("interface_" + ip ) do +      setcode do +        interface +      end +    end +  end +end + diff --git a/puppet/modules/site_config/manifests/caching_resolver.pp b/puppet/modules/site_config/manifests/caching_resolver.pp new file mode 100644 index 00000000..8bf465c1 --- /dev/null +++ b/puppet/modules/site_config/manifests/caching_resolver.pp @@ -0,0 +1,27 @@ +# deploy local caching resolver +class site_config::caching_resolver { +  tag 'leap_base' + +  class { 'unbound': +    root_hints => false, +    anchor     => false, +    ssl        => false, +    settings   => { +      server => { +        verbosity      => '1', +        interface      => [ '127.0.0.1', '::1' ], +        port           => '53', +        hide-identity  => 'yes', +        hide-version   => 'yes', +        harden-glue    => 'yes', +        access-control => [ '127.0.0.0/8 allow', '::1 allow' ] +      } +    } +  } + +  concat::fragment { 'unbound glob include': +    target  => $unbound::params::config, +    content => "include: /etc/unbound/unbound.conf.d/*.conf\n\n", +    order   => 10 +  } +} diff --git a/puppet/modules/site_config/manifests/default.pp b/puppet/modules/site_config/manifests/default.pp new file mode 100644 index 00000000..256de1a1 --- /dev/null +++ b/puppet/modules/site_config/manifests/default.pp @@ -0,0 +1,71 @@ +# common things to set up on every node +class site_config::default { +  tag 'leap_base' + +  $services    = hiera('services', []) +  $domain_hash = hiera('domain') +  include site_config::params +  include site_config::setup + +  # default class, used by all hosts + +  include lsb, git + +  # configure sysctl parameters +  include site_config::sysctl + +  # configure ssh and include ssh-keys +  include site_sshd + +  # include classes for special environments +  # i.e. openstack/aws nodes, vagrant nodes + +  # fix dhclient from changing resolver information +  # facter returns 'true' as string +  # lint:ignore:quoted_booleans +  if $::dhcp_enabled == 'true' { +  # lint:endignore +    include site_config::dhclient +  } + +  # configure /etc/resolv.conf +  include site_config::resolvconf + +  # configure caching, local resolver +  include site_config::caching_resolver + +  # install/configure syslog and core log rotations +  include site_config::syslog + +  # provide a basic level of quality entropy +  include haveged + +  # install/remove base packages +  include site_config::packages + +  # include basic shorewall config +  include site_shorewall::defaults + +  Package['git'] -> Vcsrepo<||> + +  # include basic shell config +  include site_config::shell + +  # set up core leap files and directories +  include site_config::files + +  # remove leftovers from previous deploys +  include site_config::remove + +  if ! member($services, 'mx') { +    include site_postfix::satellite +  } + +  # if class custom exists, include it. +  # possibility for users to define custom puppet recipes +  if defined( '::custom') { +    include ::custom +  } + +  include site_check_mk::agent +} diff --git a/puppet/modules/site_config/manifests/dhclient.pp b/puppet/modules/site_config/manifests/dhclient.pp new file mode 100644 index 00000000..a1f87d41 --- /dev/null +++ b/puppet/modules/site_config/manifests/dhclient.pp @@ -0,0 +1,40 @@ +# Unfortunately, there does not seem to be a way to reload the dhclient.conf +# config file, or a convenient way to disable the modifications to +# /etc/resolv.conf. So the following makes the functions involved noops and +# ships a script to kill and restart dhclient. See the debian bugs: +# #681698, #712796 +class site_config::dhclient { + + +  include site_config::params + +  file { '/usr/local/sbin/reload_dhclient': +    owner   => 0, +    group   => 0, +    mode    => '0755', +    content => template('site_config/reload_dhclient.erb'); +  } + +  exec { 'reload_dhclient': +    refreshonly => true, +    command     => '/usr/local/sbin/reload_dhclient', +    before      => Class['site_config::resolvconf'], +    require     => File['/usr/local/sbin/reload_dhclient'], +  } + +  file { '/etc/dhcp/dhclient-enter-hooks.d': +    ensure => directory, +    mode   => '0755', +    owner  => 'root', +    group  => 'root', +  } + +  file { '/etc/dhcp/dhclient-enter-hooks.d/disable_resolvconf': +    content => 'make_resolv_conf() { : ; } ; set_hostname() { : ; }', +    mode    => '0644', +    owner   => 'root', +    group   => 'root', +    require => File['/etc/dhcp/dhclient-enter-hooks.d'], +    notify  => Exec['reload_dhclient']; +  } +} diff --git a/puppet/modules/site_config/manifests/files.pp b/puppet/modules/site_config/manifests/files.pp new file mode 100644 index 00000000..d2ef8a98 --- /dev/null +++ b/puppet/modules/site_config/manifests/files.pp @@ -0,0 +1,24 @@ +# set up core leap files and directories +class site_config::files { + +  file { +    '/srv/leap': +      ensure  => directory, +      owner   => 'root', +      group   => 'root', +      mode    => '0711'; + +    [ '/etc/leap', '/var/lib/leap']: +      ensure => directory, +      owner  => 'root', +      group  => 'root', +      mode   => '0755'; + +    '/var/log/leap': +      ensure => directory, +      owner  => 'root', +      group  => 'adm', +      mode   => '0750'; +  } + +} diff --git a/puppet/modules/site_config/manifests/hosts.pp b/puppet/modules/site_config/manifests/hosts.pp new file mode 100644 index 00000000..878b6af0 --- /dev/null +++ b/puppet/modules/site_config/manifests/hosts.pp @@ -0,0 +1,44 @@ +class site_config::hosts() { +  $hosts         = hiera('hosts', false) + +  # calculate all the hostname aliases that might be used +  $hostname      = hiera('name') +  $domain_hash   = hiera('domain', {}) +  $dns           = hiera('dns', {}) +  if $dns['aliases'] == undef { +    $dns_aliases = [] +  } else { +    $dns_aliases = $dns['aliases'] +  } +  $my_hostnames = unique(concat( +    [$domain_hash['full'], $hostname, $domain_hash['internal']], $dns_aliases +  )) + +  file { '/etc/hostname': +    ensure  => present, +    content => $hostname +  } + +  exec { "/bin/hostname ${hostname}": +    subscribe   => [ File['/etc/hostname'], File['/etc/hosts'] ], +    refreshonly => true; +  } + +  # we depend on reliable hostnames from /etc/hosts for the stunnel services +  # so restart stunnel service when /etc/hosts is modified +  # because this is done in an early stage, the stunnel module may not +  # have been deployed and will not be available for overriding, so +  # this is handled in an unorthodox manner +  exec { '/etc/init.d/stunnel4 restart': +    subscribe   => File['/etc/hosts'], +    refreshonly => true, +    onlyif      => 'test -f /etc/init.d/stunnel4'; +  } + +  file { '/etc/hosts': +    content => template('site_config/hosts'), +    mode    => '0644', +    owner   => root, +    group   => root; +  } +} diff --git a/puppet/modules/site_config/manifests/initial_firewall.pp b/puppet/modules/site_config/manifests/initial_firewall.pp new file mode 100644 index 00000000..93cfb847 --- /dev/null +++ b/puppet/modules/site_config/manifests/initial_firewall.pp @@ -0,0 +1,64 @@ +class site_config::initial_firewall { + +  # This class is intended to setup an initial firewall, before shorewall is +  # configured. The purpose of this is for the rare case where shorewall fails +  # to start, we should not expose services to the public. + +  $ssh_config = hiera('ssh') +  $ssh_port   = $ssh_config['port'] + +  package { 'iptables': +    ensure => present +  } + +  file { +    # This firewall enables ssh access, dns lookups and web lookups (for +    # package installation) but otherwise restricts all outgoing and incoming +    # ports +    '/etc/network/ipv4firewall_up.rules': +      content => template('site_config/ipv4firewall_up.rules.erb'), +      owner   => root, +      group   => 0, +      mode    => '0644'; + +    # This firewall denys all ipv6 traffic - we will need to change this +    # when we begin to support ipv6 +    '/etc/network/ipv6firewall_up.rules': +      content => template('site_config/ipv6firewall_up.rules.erb'), +      owner   => root, +      group   => 0, +      mode    => '0644'; + +    # Run the iptables-restore in if-pre-up so that the network is locked down +    # until the correct interfaces and ips are connected +    '/etc/network/if-pre-up.d/ipv4tables': +      content => "#!/bin/sh\n/sbin/iptables-restore < /etc/network/ipv4firewall_up.rules\n", +      owner   => root, +      group   => 0, +      mode    => '0744'; + +    # Same as above for IPv6 +    '/etc/network/if-pre-up.d/ipv6tables': +      content => "#!/bin/sh\n/sbin/ip6tables-restore < /etc/network/ipv6firewall_up.rules\n", +      owner   => root, +      group   => 0, +      mode    => '0744'; +  } + +  # Immediately setup these firewall rules, but only if shorewall is not running +  exec { +    'default_ipv4_firewall': +      command   => '/sbin/iptables-restore < /etc/network/ipv4firewall_up.rules', +      logoutput => true, +      unless    => 'test -x /etc/init.d/shorewall && /etc/init.d/shorewall status', +      subscribe => File['/etc/network/ipv4firewall_up.rules'], +      require   => File['/etc/network/ipv4firewall_up.rules']; + +    'default_ipv6_firewall': +      command   => '/sbin/ip6tables-restore < /etc/network/ipv6firewall_up.rules', +      logoutput => true, +      unless    => 'test -x /etc/init.d/shorewall6 && /etc/init.d/shorewall6 status', +      subscribe => File['/etc/network/ipv6firewall_up.rules'], +      require   => File['/etc/network/ipv6firewall_up.rules']; +  } +} diff --git a/puppet/modules/site_config/manifests/packages.pp b/puppet/modules/site_config/manifests/packages.pp new file mode 100644 index 00000000..140189a4 --- /dev/null +++ b/puppet/modules/site_config/manifests/packages.pp @@ -0,0 +1,32 @@ +# install default packages and remove unwanted packages +class site_config::packages { + + +  # base set of packages that we want to have installed everywhere +  package { [ 'etckeeper', 'screen', 'less', 'ntp' ]: +    ensure => installed, +  } + +  # base set of packages that we want to remove everywhere +  package { [ +    'acpi', 'build-essential', +    'cpp', 'cpp-4.6', 'cpp-4.7', 'cpp-4.8', 'cpp-4.9', +    'eject', 'ftp', +    'g++', 'g++-4.6', 'g++-4.7', 'g++-4.8', 'g++-4.9', +    'gcc', 'gcc-4.6', 'gcc-4.7', 'gcc-4.8', 'gcc-4.9', +    'laptop-detect', 'libc6-dev', 'libssl-dev', 'lpr', 'make', +    'pppconfig', 'pppoe', 'pump', 'qstat', +    'samba-common', 'samba-common-bin', 'smbclient', +    'tcl8.5', 'tk8.5', 'os-prober', 'unzip', 'xauth', 'x11-common', +    'x11-utils', 'xterm' ]: +      ensure => purged; +  } + +  # leave a few packages installed on local environments +  # vagrant i.e. needs them for mounting shared folders +    if $::site_config::params::environment != 'local' { +    package { [ 'nfs-common', 'nfs-kernel-server', 'rpcbind', 'portmap' ]: +      ensure => purged; +    } +  } +} diff --git a/puppet/modules/site_config/manifests/packages/build_essential.pp b/puppet/modules/site_config/manifests/packages/build_essential.pp new file mode 100644 index 00000000..2b3e13b9 --- /dev/null +++ b/puppet/modules/site_config/manifests/packages/build_essential.pp @@ -0,0 +1,28 @@ +# +# include this whenever you want to ensure build-essential package and related compilers are installed. +# +class site_config::packages::build_essential inherits ::site_config::packages { + +  # NICKSERVER CODE NOTE: in order to support TLS, libssl-dev must be installed +  # before EventMachine gem is built/installed. +  Package[ 'gcc', 'make', 'g++', 'cpp', 'libssl-dev', 'libc6-dev' ] { +    ensure => present +  } + +  case $::operatingsystemrelease { +    /^8.*/: { +      Package[ 'gcc-4.9','g++-4.9', 'cpp-4.9' ] { +        ensure => present +      } +    } + +    /^7.*/: { +      Package[ 'gcc-4.7','g++-4.7', 'cpp-4.7' ] { +        ensure => present +      } +    } + +    default:  { } +  } + +} diff --git a/puppet/modules/site_config/manifests/packages/gnutls.pp b/puppet/modules/site_config/manifests/packages/gnutls.pp new file mode 100644 index 00000000..b1f17480 --- /dev/null +++ b/puppet/modules/site_config/manifests/packages/gnutls.pp @@ -0,0 +1,5 @@ +class site_config::packages::gnutls { + +  package { 'gnutls-bin': ensure => installed } + +} diff --git a/puppet/modules/site_config/manifests/params.pp b/puppet/modules/site_config/manifests/params.pp new file mode 100644 index 00000000..012b3ce0 --- /dev/null +++ b/puppet/modules/site_config/manifests/params.pp @@ -0,0 +1,35 @@ +class site_config::params { + +  $ip_address               = hiera('ip_address') +  $ip_address_interface     = getvar("interface_${ip_address}") +  $ec2_local_ipv4_interface = getvar("interface_${::ec2_local_ipv4}") +  $environment              = hiera('environment', undef) + + +  if $environment == 'local' { +    $interface = 'eth1' +    include site_config::packages::build_essential +  } +  elsif hiera('interface','') != '' { +    $interface = hiera('interface') +  } +  elsif $ip_address_interface != '' { +    $interface = $ip_address_interface +  } +  elsif $ec2_local_ipv4_interface != '' { +    $interface = $ec2_local_ipv4_interface +  } +  elsif $::interfaces =~ /eth0/ { +    $interface = 'eth0' +  } +  else { +    fail("unable to determine a valid interface, please set a valid interface for this node in nodes/${::hostname}.json") +  } + +  $ca_name              = 'leap_ca' +  $client_ca_name       = 'leap_client_ca' +  $ca_bundle_name       = 'leap_ca_bundle' +  $cert_name            = 'leap' +  $commercial_ca_name   = 'leap_commercial_ca' +  $commercial_cert_name = 'leap_commercial' +} diff --git a/puppet/modules/site_config/manifests/remove.pp b/puppet/modules/site_config/manifests/remove.pp new file mode 100644 index 00000000..443df9c2 --- /dev/null +++ b/puppet/modules/site_config/manifests/remove.pp @@ -0,0 +1,11 @@ +# remove leftovers from previous deploys +class site_config::remove { +  include site_config::remove::files + +  case $::operatingsystemrelease { +    /^8.*/: { +      include site_config::remove::jessie +    } +    default:  { } +  } +} diff --git a/puppet/modules/site_config/manifests/remove/bigcouch.pp b/puppet/modules/site_config/manifests/remove/bigcouch.pp new file mode 100644 index 00000000..3535c3c1 --- /dev/null +++ b/puppet/modules/site_config/manifests/remove/bigcouch.pp @@ -0,0 +1,42 @@ +# remove bigcouch leftovers from previous installations +class site_config::remove::bigcouch { + +  # Don't use check_mk logwatch to watch bigcouch logs anymore +  # see https://leap.se/code/issues/7375 for more details +  file { '/etc/check_mk/logwatch.d/bigcouch.cfg': +    ensure => absent, +    notify => [ +      Exec['remove_bigcouch_logwatch_stateline'] +    ] +  } + +  exec { 'remove_bigcouch_logwatch_stateline': +    command     => "sed -i '/bigcouch.log/d' /etc/check_mk/logwatch.state", +    refreshonly => true, +  } + +  cron { 'compact_all_shards': +    ensure => absent +  } + + +  exec { 'kill_bigcouch_stunnel_procs': +    refreshonly => true, +    command     => '/usr/bin/pkill -f "/usr/bin/stunnel4 /etc/stunnel/(ednp|epmd)_server.conf"' +  } + +  # 'tidy' doesn't notify other resources, so we need to use file here instead +  # see https://tickets.puppetlabs.com/browse/PUP-6021 +  file { +    [ '/etc/stunnel/ednp_server.conf', '/etc/stunnel/epmd_server.conf']: +      ensure => absent, +      # notifying Service[stunnel] doesn't work here because the config +      # files contain the pid of the procs to stop/start. +      # If we remove the config, and restart stunnel then it will only +      # stop/start the procs for which config files are found and the stale +      # service will continue to run. +      # So we simply kill them. +      notify => Exec['kill_bigcouch_stunnel_procs'] +  } + +} diff --git a/puppet/modules/site_config/manifests/remove/files.pp b/puppet/modules/site_config/manifests/remove/files.pp new file mode 100644 index 00000000..41d6462e --- /dev/null +++ b/puppet/modules/site_config/manifests/remove/files.pp @@ -0,0 +1,56 @@ +# +# Sometimes when we upgrade the platform, we need to ensure that files that +# the platform previously created will get removed. +# +# These file removals don't need to be kept forever: we only need to remove +# files that are present in the prior platform release. +# +# We can assume that the every node is upgraded from the previous platform +# release. +# + +class site_config::remove::files { + +  # Platform 0.8 removals +  tidy { +    '/etc/default/leap_mx':; +    '/etc/logrotate.d/mx':; +    '/etc/rsyslog.d/50-mx.conf':; +    '/etc/apt/preferences.d/openvpn':; +    '/etc/apt/sources.list.d/secondary.list.disabled.list':; +  } + +  # +  # Platform 0.7 removals +  # + +  tidy { +    '/etc/rsyslog.d/99-tapicero.conf':; +    '/etc/rsyslog.d/01-webapp.conf':; +    '/etc/rsyslog.d/50-stunnel.conf':; +    '/etc/logrotate.d/stunnel':; +    '/var/log/stunnel4/stunnel.log':; +    'leap_mx': +      path => '/var/log/', +      recurse => true, +      matches => ['leap_mx*', 'mx.log.[1-5]', 'mx.log.[6-9](.gz)?', +                  'mx.log.[0-9][0-9](.gz)?']; +    '/srv/leap/webapp/public/provider.json':; +    '/srv/leap/couchdb/designs/tmp_users': +      recurse => true, +      rmdirs => true; +    '/etc/leap/soledad-server.conf':; +    '/var/log/leap/openvpn.log':; +    '/etc/rsyslog.d/50-openvpn.conf':; +  } + +  # leax-mx logged to /var/log/leap_mx.log in the past +  # we need to use a dumb exec here because file_line doesn't +  # allow removing lines that match a regex in the current version +  # of stdlib, see https://tickets.puppetlabs.com/browse/MODULES-1903 +  exec { 'rm_old_leap_mx_log_destination': +      command => "/bin/sed -i '/leap_mx.log/d' /etc/check_mk/logwatch.state", +      onlyif  => "/bin/grep -qe 'leap_mx.log' /etc/check_mk/logwatch.state" +  } + +} diff --git a/puppet/modules/site_config/manifests/remove/jessie.pp b/puppet/modules/site_config/manifests/remove/jessie.pp new file mode 100644 index 00000000..e9497baf --- /dev/null +++ b/puppet/modules/site_config/manifests/remove/jessie.pp @@ -0,0 +1,14 @@ +# remove possible leftovers after upgrading from wheezy to jessie +class site_config::remove::jessie { + +  tidy { +    '/etc/apt/preferences.d/rsyslog_anon_depends': +      notify => Exec['apt_updated']; +  } + +  apt::preferences_snippet { +    [ 'facter', 'obfsproxy', 'python-twisted', 'unbound' ]: +      ensure => absent; +  } + +} diff --git a/puppet/modules/site_config/manifests/remove/monitoring.pp b/puppet/modules/site_config/manifests/remove/monitoring.pp new file mode 100644 index 00000000..18e2949b --- /dev/null +++ b/puppet/modules/site_config/manifests/remove/monitoring.pp @@ -0,0 +1,13 @@ +# remove leftovers on monitoring nodes +class site_config::remove::monitoring { + +  # Remove check_mk loggwatch spoolfiles for +  # tapicero and bigcouch +  tidy { +    'remove_logwatch_spoolfiles': +      path    => '/var/lib/check_mk/logwatch', +      recurse => true, +      matches => [ '*tapicero.log', '*bigcouch.log']; +  } + +} diff --git a/puppet/modules/site_config/manifests/remove/tapicero.pp b/puppet/modules/site_config/manifests/remove/tapicero.pp new file mode 100644 index 00000000..07c3c6c6 --- /dev/null +++ b/puppet/modules/site_config/manifests/remove/tapicero.pp @@ -0,0 +1,72 @@ +# remove tapicero leftovers from previous deploys on couchdb nodes +class site_config::remove::tapicero { + +  ensure_packages('curl') + +  # remove tapicero couchdb user +  $couchdb_config = hiera('couch') +  $couchdb_mode   = $couchdb_config['mode'] + +  if $couchdb_mode == 'multimaster' +  { +    $port = 5986 +  } else { +    $port = 5984 +  } + +  exec { 'remove_couchdb_user': +    onlyif  => "/usr/bin/curl -s 127.0.0.1:${port}/_users/org.couchdb.user:tapicero | grep -qv 'not_found'", +    command => "/usr/local/bin/couch-doc-update --host 127.0.0.1:${port} --db _users --id org.couchdb.user:tapicero --delete", +    require => Package['curl'] +  } + + +  exec { 'kill_tapicero': +    onlyif  => '/usr/bin/test -s /var/run/tapicero.pid', +    command => '/usr/bin/pkill --pidfile /var/run/tapicero.pid' +  } + +  user { 'tapicero': +    ensure  => absent; +  } + +  group { 'tapicero': +    ensure => absent, +    require => User['tapicero']; +  } + +  tidy { +    '/srv/leap/tapicero': +      recurse => true, +      require   => [ Exec['kill_tapicero'] ]; +    '/var/lib/leap/tapicero': +      require   => [ Exec['kill_tapicero'] ]; +    '/var/run/tapicero': +      require   => [ Exec['kill_tapicero'] ]; +    '/etc/leap/tapicero.yaml': +      require   => [ Exec['kill_tapicero'] ]; +    '/etc/init.d/tapicero': +      require   => [ Exec['kill_tapicero'] ]; +    'tapicero_logs': +      path    => '/var/log/leap', +      recurse => true, +      matches => 'tapicero*', +      require   => [ Exec['kill_tapicero'] ]; +    '/etc/check_mk/logwatch.d/tapicero.cfg':; +  } + +  # remove local nagios plugin checks via mrpe +  augeas { +    'Tapicero_Procs': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => 'rm /files/etc/check_mk/mrpe.cfg/Tapicero_Procs', +      require => File['/etc/check_mk/mrpe.cfg']; +    'Tapicero_Heartbeat': +      incl    => '/etc/check_mk/mrpe.cfg', +      lens    => 'Spacevars.lns', +      changes => 'rm Tapicero_Heartbeat', +      require => File['/etc/check_mk/mrpe.cfg']; +  } + +} diff --git a/puppet/modules/site_config/manifests/remove/webapp.pp b/puppet/modules/site_config/manifests/remove/webapp.pp new file mode 100644 index 00000000..58f59815 --- /dev/null +++ b/puppet/modules/site_config/manifests/remove/webapp.pp @@ -0,0 +1,7 @@ +# remove leftovers on webapp nodes +class site_config::remove::webapp { +  tidy { +    '/etc/apache/sites-enabled/leap_webapp.conf': +      notify => Service['apache']; +  } +} diff --git a/puppet/modules/site_config/manifests/resolvconf.pp b/puppet/modules/site_config/manifests/resolvconf.pp new file mode 100644 index 00000000..09f0b405 --- /dev/null +++ b/puppet/modules/site_config/manifests/resolvconf.pp @@ -0,0 +1,14 @@ +class site_config::resolvconf { + +  $domain_public = $site_config::default::domain_hash['full_suffix'] + +  class { '::resolvconf': +    domain      => $domain_public, +    search      => $domain_public, +    nameservers => [ +      '127.0.0.1      # local caching-only, unbound', +      '85.214.20.141  # Digitalcourage, a german privacy organisation: (https://en.wikipedia.org/wiki/Digitalcourage)', +      '172.81.176.146 # OpenNIC (https://servers.opennicproject.org/edit.php?srv=ns1.tor.ca.dns.opennic.glue)' +    ] +  } +} diff --git a/puppet/modules/site_config/manifests/ruby.pp b/puppet/modules/site_config/manifests/ruby.pp new file mode 100644 index 00000000..5c13233d --- /dev/null +++ b/puppet/modules/site_config/manifests/ruby.pp @@ -0,0 +1,8 @@ +# install ruby, rubygems and bundler +# configure ruby settings common to all servers +class site_config::ruby { +  Class[Ruby] -> Class[rubygems] -> Class[bundler::install] +  class { '::ruby': } +  class { 'bundler::install': install_method => 'package' } +  include rubygems +} diff --git a/puppet/modules/site_config/manifests/ruby/dev.pp b/puppet/modules/site_config/manifests/ruby/dev.pp new file mode 100644 index 00000000..2b0b106d --- /dev/null +++ b/puppet/modules/site_config/manifests/ruby/dev.pp @@ -0,0 +1,8 @@ +# install ruby dev packages needed for building some gems +class site_config::ruby::dev { +  include site_config::ruby +  include ::ruby::devel + +  # building gems locally probably requires build-essential and gcc: +  include site_config::packages::build_essential +} diff --git a/puppet/modules/site_config/manifests/setup.pp b/puppet/modules/site_config/manifests/setup.pp new file mode 100644 index 00000000..82dfe76d --- /dev/null +++ b/puppet/modules/site_config/manifests/setup.pp @@ -0,0 +1,50 @@ +# common things to set up on every node +# leftover from the past, where we did two puppetruns +# after another. We should consolidate this into site_config::default +# in the future. +class site_config::setup { +  tag 'leap_base' + +  # +  # this is applied before each run of site.pp +  # + +  Exec { path => '/usr/bin:/usr/sbin/:/bin:/sbin:/usr/local/bin:/usr/local/sbin' } + +  include site_config::params + +  include concat::setup +  include stdlib + +  # configure /etc/hosts +  class { 'site_config::hosts': } + +  include site_config::initial_firewall + +  include site_apt + +  package { 'facter': +    ensure  => latest +  } + +  # if squid_deb_proxy_client is set to true, install and configure +  # squid_deb_proxy_client for apt caching +  if hiera('squid_deb_proxy_client', false) { +    include site_squid_deb_proxy::client +  } + +  # shorewall is installed/half-configured during setup.pp (Bug #3871) +  # we need to include shorewall::interface{eth0} in setup.pp so +  # packages can be installed during main puppetrun, even before shorewall +  # is configured completly +  if ( $::site_config::params::environment == 'local' ) { +    include site_config::vagrant +  } + +  # if class site_custom::setup exists, include it. +  # possibility for users to define custom puppet recipes +  if defined( '::site_custom::setup') { +    include ::site_custom::setup +  } + +} diff --git a/puppet/modules/site_config/manifests/shell.pp b/puppet/modules/site_config/manifests/shell.pp new file mode 100644 index 00000000..5b8c025d --- /dev/null +++ b/puppet/modules/site_config/manifests/shell.pp @@ -0,0 +1,22 @@ +class site_config::shell { + +  file { +    '/etc/profile.d/leap_path.sh': +      content => 'PATH=$PATH:/srv/leap/bin', +      mode    => '0644', +      owner   => root, +      group   => root; +  } + +  ## +  ## XTERM TITLE +  ## + +  file { '/etc/profile.d/xterm-title.sh': +    source => 'puppet:///modules/site_config/xterm-title.sh', +    owner  => root, +    group  => 0, +    mode   => '0644'; +  } + +} diff --git a/puppet/modules/site_config/manifests/slow.pp b/puppet/modules/site_config/manifests/slow.pp new file mode 100644 index 00000000..8e9b7035 --- /dev/null +++ b/puppet/modules/site_config/manifests/slow.pp @@ -0,0 +1,10 @@ +# this class is run by default, but can be excluded +# for testing purposes by calling "leap deploy" with +# the "--fast" parameter +class site_config::slow { +  tag 'leap_slow' + +  include site_config::default +  include apt::update +  class { 'site_apt::dist_upgrade': } +} diff --git a/puppet/modules/site_config/manifests/sysctl.pp b/puppet/modules/site_config/manifests/sysctl.pp new file mode 100644 index 00000000..99f75123 --- /dev/null +++ b/puppet/modules/site_config/manifests/sysctl.pp @@ -0,0 +1,8 @@ +class site_config::sysctl { + +  sysctl::config { +    'net.ipv4.ip_nonlocal_bind': +      value   => 1, +      comment => 'Allow applications to bind to an address when link is down (see https://leap.se/code/issues/4506)' +  } +} diff --git a/puppet/modules/site_config/manifests/syslog.pp b/puppet/modules/site_config/manifests/syslog.pp new file mode 100644 index 00000000..591e0601 --- /dev/null +++ b/puppet/modules/site_config/manifests/syslog.pp @@ -0,0 +1,62 @@ +# configure rsyslog on all nodes +class site_config::syslog { + +  # only pin rsyslog packages to backports on wheezy +  case $::operatingsystemrelease { +    /^7.*/: { +      include ::site_apt::preferences::rsyslog +    } +    # on jessie+ systems, systemd and journald are enabled, +    # and journald logs IP addresses, so we need to disable +    # it until a solution is found, (#7863): +    # https://github.com/systemd/systemd/issues/2447 +    default: { +      include ::journald +      augeas { +        'disable_journald': +          incl    => '/etc/systemd/journald.conf', +          lens    => 'Puppet.lns', +          changes => 'set /files/etc/systemd/journald.conf/Journal/Storage \'none\'', +          notify  => Service['systemd-journald']; +      } +    } +  } + +  class { '::rsyslog::client': +    log_remote    => false, +    log_local     => true, +    custom_config => 'site_rsyslog/client.conf.erb' +  } + +  rsyslog::snippet { '00-anonymize_logs': +    content => '$ModLoad mmanon +action(type="mmanon" ipv4.bits="32" mode="rewrite")' +  } + +  augeas { +    'logrotate_leap_deploy': +      context => '/files/etc/logrotate.d/leap_deploy/rule', +      changes => [ +        'set file /var/log/leap/deploy.log', +        'set rotate 5', +        'set size 1M', +        'set compress compress', +        'set missingok missingok', +        'set copytruncate copytruncate' ]; + +    # NOTE: +    # the puppet_command script requires the option delaycompress +    # be set on the summary log file. + +    'logrotate_leap_deploy_summary': +      context => '/files/etc/logrotate.d/leap_deploy_summary/rule', +      changes => [ +        'set file /var/log/leap/deploy-summary.log', +        'set rotate 5', +        'set size 100k', +        'set delaycompress delaycompress', +        'set compress compress', +        'set missingok missingok', +        'set copytruncate copytruncate' ] +  } +} diff --git a/puppet/modules/site_config/manifests/vagrant.pp b/puppet/modules/site_config/manifests/vagrant.pp new file mode 100644 index 00000000..8f50b305 --- /dev/null +++ b/puppet/modules/site_config/manifests/vagrant.pp @@ -0,0 +1,11 @@ +class site_config::vagrant { +  # class for vagrant nodes + +  include site_shorewall::defaults +  # eth0 on vagrant nodes is the uplink if +  shorewall::interface { 'eth0': +    zone      => 'net', +    options   => 'tcpflags,blacklist,nosmurfs'; +  } + +} diff --git a/puppet/modules/site_config/manifests/x509/ca.pp b/puppet/modules/site_config/manifests/x509/ca.pp new file mode 100644 index 00000000..2880ecaf --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/ca.pp @@ -0,0 +1,11 @@ +class site_config::x509::ca { + +  include ::site_config::params + +  $x509      = hiera('x509') +  $ca        = $x509['ca_cert'] + +  x509::ca { $site_config::params::ca_name: +    content => $ca +  } +} diff --git a/puppet/modules/site_config/manifests/x509/ca_bundle.pp b/puppet/modules/site_config/manifests/x509/ca_bundle.pp new file mode 100644 index 00000000..5808e29e --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/ca_bundle.pp @@ -0,0 +1,17 @@ +class site_config::x509::ca_bundle { + +  # CA bundle -- we want to have the possibility of allowing multiple CAs. +  # For now, the reason is to transition to using client CA. In the future, +  # we will want to be able to smoothly phase out one CA and phase in another. +  # I tried "--capath" for this, but it did not work. + +  include ::site_config::params + +  $x509      = hiera('x509') +  $ca        = $x509['ca_cert'] +  $client_ca = $x509['client_ca_cert'] + +  x509::ca { $site_config::params::ca_bundle_name: +    content => "${ca}${client_ca}" +  } +} diff --git a/puppet/modules/site_config/manifests/x509/cert.pp b/puppet/modules/site_config/manifests/x509/cert.pp new file mode 100644 index 00000000..7e5a36b9 --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/cert.pp @@ -0,0 +1,12 @@ +class site_config::x509::cert { + +  include ::site_config::params + +  $x509      = hiera('x509') +  $cert      = $x509['cert'] + +  x509::cert { $site_config::params::cert_name: +    content => $cert +  } + +} diff --git a/puppet/modules/site_config/manifests/x509/client_ca/ca.pp b/puppet/modules/site_config/manifests/x509/client_ca/ca.pp new file mode 100644 index 00000000..3fbafa98 --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/client_ca/ca.pp @@ -0,0 +1,16 @@ +class site_config::x509::client_ca::ca { + +  ## +  ## This is for the special CA that is used exclusively for generating +  ## client certificates by the webapp. +  ## + +  include ::site_config::params + +  $x509 = hiera('x509') +  $cert = $x509['client_ca_cert'] + +  x509::ca { $site_config::params::client_ca_name: +    content => $cert +  } +} diff --git a/puppet/modules/site_config/manifests/x509/client_ca/key.pp b/puppet/modules/site_config/manifests/x509/client_ca/key.pp new file mode 100644 index 00000000..0b537e76 --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/client_ca/key.pp @@ -0,0 +1,16 @@ +class site_config::x509::client_ca::key { + +  ## +  ## This is for the special CA that is used exclusively for generating +  ## client certificates by the webapp. +  ## + +  include ::site_config::params + +  $x509 = hiera('x509') +  $key  = $x509['client_ca_key'] + +  x509::key { $site_config::params::client_ca_name: +    content => $key +  } +} diff --git a/puppet/modules/site_config/manifests/x509/commercial/ca.pp b/puppet/modules/site_config/manifests/x509/commercial/ca.pp new file mode 100644 index 00000000..c76a9dbb --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/commercial/ca.pp @@ -0,0 +1,11 @@ +class site_config::x509::commercial::ca { + +  include ::site_config::params + +  $x509      = hiera('x509') +  $ca        = $x509['commercial_ca_cert'] + +  x509::ca { $site_config::params::commercial_ca_name: +    content => $ca +  } +} diff --git a/puppet/modules/site_config/manifests/x509/commercial/cert.pp b/puppet/modules/site_config/manifests/x509/commercial/cert.pp new file mode 100644 index 00000000..9dd6ffcd --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/commercial/cert.pp @@ -0,0 +1,15 @@ +class site_config::x509::commercial::cert { + +  include ::site_config::params + +  $x509      = hiera('x509') +  $cert      = $x509['commercial_cert'] +  $ca        = $x509['commercial_ca_cert'] + +  $cafile = "${cert}\n${ca}" + +  x509::cert { $site_config::params::commercial_cert_name: +    content => $cafile +  } + +} diff --git a/puppet/modules/site_config/manifests/x509/commercial/key.pp b/puppet/modules/site_config/manifests/x509/commercial/key.pp new file mode 100644 index 00000000..2be439fd --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/commercial/key.pp @@ -0,0 +1,11 @@ +class site_config::x509::commercial::key { + +  include ::site_config::params + +  $x509      = hiera('x509') +  $key       = $x509['commercial_key'] + +  x509::key { $site_config::params::commercial_cert_name: +    content => $key +  } +} diff --git a/puppet/modules/site_config/manifests/x509/key.pp b/puppet/modules/site_config/manifests/x509/key.pp new file mode 100644 index 00000000..448dc6a6 --- /dev/null +++ b/puppet/modules/site_config/manifests/x509/key.pp @@ -0,0 +1,11 @@ +class site_config::x509::key { + +  include ::site_config::params + +  $x509      = hiera('x509') +  $key       = $x509['key'] + +  x509::key { $site_config::params::cert_name: +    content => $key +  } +} diff --git a/puppet/modules/site_config/templates/hosts b/puppet/modules/site_config/templates/hosts new file mode 100644 index 00000000..d62cbc3f --- /dev/null +++ b/puppet/modules/site_config/templates/hosts @@ -0,0 +1,19 @@ +# This file is managed by puppet, any changes will be overwritten! + +127.0.0.1    localhost +127.0.1.1    <%= @my_hostnames.join(' ') %> + +<%- if @hosts then -%> +<%   @hosts.keys.sort.each do |name| -%> +<%-     props = @hosts[name] -%> +<%-     aliases = props["aliases"] ? props["aliases"].join(' ') : nil -%> +<%=     [props["ip_address"], props["domain_full"], props["domain_internal"], aliases, name].compact.uniq.join(' ') %> +<%   end -%> +<% end -%> + +# The following lines are desirable for IPv6 capable hosts +::1     ip6-localhost ip6-loopback +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters diff --git a/puppet/modules/site_config/templates/ipv4firewall_up.rules.erb b/puppet/modules/site_config/templates/ipv4firewall_up.rules.erb new file mode 100644 index 00000000..b0c2b7ad --- /dev/null +++ b/puppet/modules/site_config/templates/ipv4firewall_up.rules.erb @@ -0,0 +1,14 @@ +# Generated by iptables-save v1.4.14 on Tue Aug 20 14:40:40 2013 +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] +-A INPUT -i lo -j ACCEPT +-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT +-A INPUT -p tcp -m state --state NEW,ESTABLISHED --dport 22 -j ACCEPT +-A INPUT -p tcp -m state --state NEW,ESTABLISHED --dport <%= @ssh_port %> -j ACCEPT +-A INPUT -p udp -m udp --sport 53 -j ACCEPT +-A INPUT -p icmp -m icmp --icmp-type 8 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT +-A INPUT -p icmp -m icmp --icmp-type 0 -m state --state RELATED,ESTABLISHED -j ACCEPT +-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 +COMMIT diff --git a/puppet/modules/site_config/templates/ipv6firewall_up.rules.erb b/puppet/modules/site_config/templates/ipv6firewall_up.rules.erb new file mode 100644 index 00000000..e2c92524 --- /dev/null +++ b/puppet/modules/site_config/templates/ipv6firewall_up.rules.erb @@ -0,0 +1,8 @@ +# Generated by ip6tables-save v1.4.20 on Tue Aug 20 12:19:43 2013 +*filter +:INPUT DROP [24:1980] +:FORWARD DROP [0:0] +:OUTPUT DROP [14:8030] +-A OUTPUT -j REJECT --reject-with icmp6-port-unreachable +COMMIT +# Completed on Tue Aug 20 12:19:43 2013 diff --git a/puppet/modules/site_config/templates/reload_dhclient.erb b/puppet/modules/site_config/templates/reload_dhclient.erb new file mode 100644 index 00000000..075828b7 --- /dev/null +++ b/puppet/modules/site_config/templates/reload_dhclient.erb @@ -0,0 +1,13 @@ +#!/bin/sh + +# Get the PID +PIDFILE='/var/run/dhclient.<%= scope.lookupvar('site_config::params::interface') %>.pid' + +# Capture how dhclient is currently running so we can relaunch it +dhclient=`/bin/ps --no-headers --pid $(cat $PIDFILE) -f | /usr/bin/awk '{for(i=8;i<=NF;++i) printf("%s ",  $i) }'` + +# Kill the current dhclient +/usr/bin/pkill -F $PIDFILE + +# Restart dhclient with the arguments it had previously +$dhclient diff --git a/puppet/modules/site_couchdb/files/couchdb_scripts_defaults.conf b/puppet/modules/site_couchdb/files/couchdb_scripts_defaults.conf new file mode 100644 index 00000000..1565e1a1 --- /dev/null +++ b/puppet/modules/site_couchdb/files/couchdb_scripts_defaults.conf @@ -0,0 +1,4 @@ +# space separated list of excluded DBs for dumping +# sourced by couchdb_dumpall.sh  +EXCLUDE_DBS='sessions tokens' + diff --git a/puppet/modules/site_couchdb/files/designs/Readme.md b/puppet/modules/site_couchdb/files/designs/Readme.md new file mode 100644 index 00000000..983f629f --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/Readme.md @@ -0,0 +1,14 @@ +This directory contains design documents for the leap platform. + +They need to be uploaded to the couch database in order to query the  +database in certain ways. + +Each subdirectory corresponds to a couch database and contains the design +documents that need to be added to that particular database. + +Here's an example of how to upload the users design document: +```bash +HOST="http://localhost:5984" +curl -X PUT $HOST/users/_design/User --data @users/User.json + +``` diff --git a/puppet/modules/site_couchdb/files/designs/customers/Customer.json b/puppet/modules/site_couchdb/files/designs/customers/Customer.json new file mode 100644 index 00000000..1b4bbddd --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/customers/Customer.json @@ -0,0 +1,18 @@ +{ +  "_id": "_design/Customer", +  "language": "javascript", +  "views": { +    "by_user_id": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'Customer') && (doc['user_id'] != null)) {\n                    emit(doc['user_id'], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    }, +    "by_braintree_customer_id": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'Customer') && (doc['braintree_customer_id'] != null)) {\n                    emit(doc['braintree_customer_id'], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    }, +    "all": { +      "map": "                function(doc) {\n                  if (doc['type'] == 'Customer') {\n                    emit(doc._id, null);\n                  }\n                }\n" +    } +  }, +  "couchrest-hash": "688c401ec0230b75625c176a88fc4a02" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/identities/Identity.json b/puppet/modules/site_couchdb/files/designs/identities/Identity.json new file mode 100644 index 00000000..b1c567c1 --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/identities/Identity.json @@ -0,0 +1,34 @@ +{ +  "_id": "_design/Identity", +  "language": "javascript", +  "views": { +    "by_address_and_destination": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'Identity') && (doc['address'] != null) && (doc['destination'] != null)) {\n                    emit([doc['address'], doc['destination']], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    }, +    "all": { +      "map": "                function(doc) {\n                  if (doc['type'] == 'Identity') {\n                    emit(doc._id, null);\n                  }\n                }\n" +    }, +    "cert_fingerprints_by_expiry": { +      "map": "function(doc) {\n  if (doc.type != 'Identity') {\n    return;\n  }\n  if (typeof doc.cert_fingerprints === \"object\") {\n    for (fp in doc.cert_fingerprints) {\n      if (doc.cert_fingerprints.hasOwnProperty(fp)) {\n        emit(doc.cert_fingerprints[fp], fp);\n      }\n    }\n  }\n}\n" +    }, +    "cert_expiry_by_fingerprint": { +      "map": "function(doc) {\n  if (doc.type != 'Identity') {\n    return;\n  }\n  if (typeof doc.cert_fingerprints === \"object\") {\n    for (fp in doc.cert_fingerprints) {\n      if (doc.cert_fingerprints.hasOwnProperty(fp)) {\n        emit(fp, doc.cert_fingerprints[fp]);\n      }\n    }\n  }\n}\n" +    }, +    "disabled": { +      "map": "function(doc) {\n  if (doc.type != 'Identity') {\n    return;\n  }\n  if (typeof doc.user_id === \"undefined\") {\n    emit(doc._id, 1);\n  }\n}\n" +    }, +    "pgp_key_by_email": { +      "map": "function(doc) {\n  if (doc.type != 'Identity') {\n    return;\n  }\n  if (typeof doc.keys === \"object\") {\n    emit(doc.address, doc.keys[\"pgp\"]);\n  }\n}\n" +    }, +    "by_user_id": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'Identity') && (doc['user_id'] != null)) {\n                    emit(doc['user_id'], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    }, +    "by_address": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'Identity') && (doc['address'] != null)) {\n                    emit(doc['address'], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    } +  }, +  "couchrest-hash": "4a774c3f56122b655a314670403b27e2" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/invite_codes/InviteCode.json b/puppet/modules/site_couchdb/files/designs/invite_codes/InviteCode.json new file mode 100644 index 00000000..006c1ea1 --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/invite_codes/InviteCode.json @@ -0,0 +1,22 @@ +{ +   "_id": "_design/InviteCode", +   "language": "javascript", +   "views": { +       "by__id": { +           "map": "                function(doc) {\n                  if ((doc['type'] == 'InviteCode') && (doc['_id'] != null)) {\n                    emit(doc['_id'], 1);\n                  }\n                }\n", +           "reduce": "_sum" +       }, +       "by_invite_code": { +           "map": "                function(doc) {\n                  if ((doc['type'] == 'InviteCode') && (doc['invite_code'] != null)) {\n                    emit(doc['invite_code'], 1);\n                  }\n                }\n", +           "reduce": "_sum" +       }, +       "by_invite_count": { +           "map": "                function(doc) {\n                  if ((doc['type'] == 'InviteCode') && (doc['invite_count'] != null)) {\n                    emit(doc['invite_count'], 1);\n                  }\n                }\n", +           "reduce": "_sum" +       }, +       "all": { +           "map": "                function(doc) {\n                  if (doc['type'] == 'InviteCode') {\n                    emit(doc._id, null);\n                  }\n                }\n" +       } +   }, +   "couchrest-hash": "83fb8f504520b4a9c7ddbb7928cd0ce3" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/messages/Message.json b/puppet/modules/site_couchdb/files/designs/messages/Message.json new file mode 100644 index 00000000..6a48fc4d --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/messages/Message.json @@ -0,0 +1,18 @@ +{ +  "_id": "_design/Message", +  "language": "javascript", +  "views": { +    "by_user_ids_to_show": { +      "map": "function (doc) {\n  if (doc.type === 'Message' && doc.user_ids_to_show && Array.isArray(doc.user_ids_to_show)) {\n    doc.user_ids_to_show.forEach(function (userId) {\n      emit(userId, 1);\n    });\n  }\n}\n", +      "reduce": "          function(key, values, rereduce) {\n            return sum(values);\n          }\n" +    }, +    "by_user_ids_to_show_and_created_at": { +      "map": "// not using at moment\n// call with something like Message.by_user_ids_to_show_and_created_at.startkey([user_id, start_date]).endkey([user_id,end_date])\nfunction (doc) {\n  if (doc.type === 'Message' && doc.user_ids_to_show && Array.isArray(doc.user_ids_to_show)) {\n    doc.user_ids_to_show.forEach(function (userId) {\n      emit([userId, doc.created_at], 1);\n    });\n  }\n}\n", +      "reduce": "          function(key, values, rereduce) {\n            return sum(values);\n          }\n" +    }, +    "all": { +      "map": "                function(doc) {\n                  if (doc['type'] == 'Message') {\n                    emit(doc._id, null);\n                  }\n                }\n" +    } +  }, +  "couchrest-hash": "ba80168e51015d2678cad88fc6c5b986" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/sessions/Session.json b/puppet/modules/site_couchdb/files/designs/sessions/Session.json new file mode 100644 index 00000000..70202780 --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/sessions/Session.json @@ -0,0 +1,8 @@ +{ +   "views": { +       "by_expires": { +           "reduce": "_sum", +           "map": "function(doc) {\n  if(typeof doc.expires !== \"undefined\") {\n    emit(doc.expires, 1);\n  }\n}\n" +       } +   } +} diff --git a/puppet/modules/site_couchdb/files/designs/shared/docs.json b/puppet/modules/site_couchdb/files/designs/shared/docs.json new file mode 100644 index 00000000..004180cd --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/shared/docs.json @@ -0,0 +1,8 @@ +{ +   "_id": "_design/docs",  +   "views": { +      "get": { +         "map": "function(doc) {\n    if (doc.u1db_rev) {\n        var is_tombstone = true;\n        var has_conflicts = false;\n        if (doc._attachments) {\n            if (doc._attachments.u1db_content)\n                is_tombstone = false;\n            if (doc._attachments.u1db_conflicts)\n                has_conflicts = true;\n        }\n        emit(doc._id,\n            {\n                \"couch_rev\": doc._rev,\n                \"u1db_rev\": doc.u1db_rev,\n                \"is_tombstone\": is_tombstone,\n                \"has_conflicts\": has_conflicts,\n            }\n        );\n    }\n}\n" +      } +   } +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/shared/syncs.json b/puppet/modules/site_couchdb/files/designs/shared/syncs.json new file mode 100644 index 00000000..bab5622f --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/shared/syncs.json @@ -0,0 +1,11 @@ +{ +   "_id": "_design/syncs",  +   "updates": { +      "put": "function(doc, req){\n    if (!doc) {\n        doc = {}\n        doc['_id'] = 'u1db_sync_log';\n        doc['syncs'] = [];\n    }\n    body = JSON.parse(req.body);\n    // remove outdated info\n    doc['syncs'] = doc['syncs'].filter(\n        function (entry) {\n            return entry[0] != body['other_replica_uid'];\n        }\n    );\n    // store u1db rev\n    doc['syncs'].push([\n        body['other_replica_uid'],\n        body['other_generation'],\n        body['other_transaction_id']\n    ]);\n    return [doc, 'ok'];\n}\n\n" +   },  +   "views": { +      "log": { +         "map": "function(doc) {\n    if (doc._id == 'u1db_sync_log') {\n        if (doc.syncs)\n            doc.syncs.forEach(function (entry) {\n                emit(entry[0],\n                    {\n                        'known_generation': entry[1],\n                        'known_transaction_id': entry[2]\n                    });\n            });\n    }\n}\n" +      } +   } +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/shared/transactions.json b/puppet/modules/site_couchdb/files/designs/shared/transactions.json new file mode 100644 index 00000000..106ad46c --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/shared/transactions.json @@ -0,0 +1,13 @@ +{ +   "_id": "_design/transactions",  +   "lists": { +      "generation": "function(head, req) {\n    var row;\n    var rows=[];\n    // fetch all rows\n    while(row = getRow()) {\n        rows.push(row);\n    }\n    if (rows.length > 0)\n        send(JSON.stringify({\n            \"generation\": rows.length,\n            \"doc_id\": rows[rows.length-1]['id'],\n            \"transaction_id\": rows[rows.length-1]['value']\n        }));\n    else\n        send(JSON.stringify({\n            \"generation\": 0,\n            \"doc_id\": \"\",\n            \"transaction_id\": \"\",\n        }));\n}\n",  +      "trans_id_for_gen": "function(head, req) {\n    var row;\n    var rows=[];\n    var i = 1;\n    var gen = 1;\n    if (req.query.gen)\n        gen = parseInt(req.query['gen']);\n    // fetch all rows\n    while(row = getRow())\n        rows.push(row);\n    if (gen <= rows.length)\n        send(JSON.stringify({\n            \"generation\": gen,\n            \"doc_id\": rows[gen-1]['id'],\n            \"transaction_id\": rows[gen-1]['value'],\n        }));\n    else\n        send('{}');\n}\n",  +      "whats_changed": "function(head, req) {\n    var row;\n    var gen = 1;\n    var old_gen = 0;\n    if (req.query.old_gen)\n        old_gen = parseInt(req.query['old_gen']);\n    send('{\"transactions\":[\\n');\n    // fetch all rows\n    while(row = getRow()) {\n        if (gen > old_gen) {\n            if (gen > old_gen+1)\n                send(',\\n');\n            send(JSON.stringify({\n                \"generation\": gen,\n                \"doc_id\": row[\"id\"],\n                \"transaction_id\": row[\"value\"]\n            }));\n        }\n        gen++;\n    }\n    send('\\n]}');\n}\n" +   },  +   "views": { +      "log": { +         "map": "function(doc) {\n    if (doc.u1db_transactions)\n        doc.u1db_transactions.forEach(function(t) {\n            emit(t[0],  // use timestamp as key so the results are ordered\n                 t[1]); // value is the transaction_id\n        });\n}\n" +      } +   } +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/tickets/Ticket.json b/puppet/modules/site_couchdb/files/designs/tickets/Ticket.json new file mode 100644 index 00000000..578f632b --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/tickets/Ticket.json @@ -0,0 +1,50 @@ +{ +  "_id": "_design/Ticket", +  "language": "javascript", +  "views": { +    "by_updated_at": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'Ticket') && (doc['updated_at'] != null)) {\n                    emit(doc['updated_at'], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    }, +    "by_created_at": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'Ticket') && (doc['created_at'] != null)) {\n                    emit(doc['created_at'], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    }, +    "by_created_by": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'Ticket') && (doc['created_by'] != null)) {\n                    emit(doc['created_by'], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    }, +    "by_is_open_and_created_at": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'Ticket') && (doc['is_open'] != null) && (doc['created_at'] != null)) {\n                    emit([doc['is_open'], doc['created_at']], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    }, +    "by_is_open_and_updated_at": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'Ticket') && (doc['is_open'] != null) && (doc['updated_at'] != null)) {\n                    emit([doc['is_open'], doc['updated_at']], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    }, +    "by_includes_post_by_and_is_open_and_created_at": { +      "map": "function(doc) {\n  var arr = {}\n  if (doc['type'] == 'Ticket' && doc.comments) {\n    doc.comments.forEach(function(comment){\n      if (comment.posted_by && !arr[comment.posted_by]) {\n        //don't add duplicates\n        arr[comment.posted_by] = true;\n        emit([comment.posted_by, doc.is_open, doc.created_at], 1);\n      }\n    });\n  }\n}\n", +      "reduce": "          function(key, values, rereduce) {\n            return sum(values);\n          }\n" +    }, +    "by_includes_post_by": { +      "map": "// TODO: This view is only used in tests--should we keep it?\nfunction(doc) {\n  var arr = {}\n  if (doc['type'] == 'Ticket' && doc.comments) {\n    doc.comments.forEach(function(comment){\n      if (comment.posted_by && !arr[comment.posted_by]) {\n        //don't add duplicates\n        arr[comment.posted_by] = true;\n        emit(comment.posted_by, 1);\n      }\n    });\n  }\n}\n", +      "reduce": "          function(key, values, rereduce) {\n            return sum(values);\n          }\n" +    }, +    "by_includes_post_by_and_is_open_and_updated_at": { +      "map": "function(doc) {\n  var arr = {}\n  if (doc['type'] == 'Ticket' && doc.comments) {\n    doc.comments.forEach(function(comment){\n      if (comment.posted_by && !arr[comment.posted_by]) {\n        //don't add duplicates\n        arr[comment.posted_by] = true;\n        emit([comment.posted_by, doc.is_open, doc.updated_at], 1);\n      }\n    });\n  }\n}\n", +      "reduce": "          function(key, values, rereduce) {\n            return sum(values);\n          }\n" +    }, +    "by_includes_post_by_and_created_at": { +      "map": "function(doc) {\n  var arr = {}\n  if (doc['type'] == 'Ticket' && doc.comments) {\n    doc.comments.forEach(function(comment){\n      if (comment.posted_by && !arr[comment.posted_by]) {\n        //don't add duplicates\n        arr[comment.posted_by] = true;\n        emit([comment.posted_by, doc.created_at], 1);\n      }\n    });\n  }\n}\n", +      "reduce": "          function(key, values, rereduce) {\n            return sum(values);\n          }\n" +    }, +    "by_includes_post_by_and_updated_at": { +      "map": "function(doc) {\n  var arr = {}\n  if (doc['type'] == 'Ticket' && doc.comments) {\n    doc.comments.forEach(function(comment){\n      if (comment.posted_by && !arr[comment.posted_by]) {\n        //don't add duplicates\n        arr[comment.posted_by] = true;\n        emit([comment.posted_by, doc.updated_at], 1);\n      }\n    });\n  }\n}\n", +      "reduce": "          function(key, values, rereduce) {\n            return sum(values);\n          }\n" +    }, +    "all": { +      "map": "                function(doc) {\n                  if (doc['type'] == 'Ticket') {\n                    emit(doc._id, null);\n                  }\n                }\n" +    } +  }, +  "couchrest-hash": "b21eaeea8ea66bfda65581b1b7ce06af" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/tokens/Token.json b/puppet/modules/site_couchdb/files/designs/tokens/Token.json new file mode 100644 index 00000000..b9025f15 --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/tokens/Token.json @@ -0,0 +1,14 @@ +{ +  "_id": "_design/Token", +  "language": "javascript", +  "views": { +    "by_last_seen_at": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'Token') && (doc['last_seen_at'] != null)) {\n                    emit(doc['last_seen_at'], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    }, +    "all": { +      "map": "                function(doc) {\n                  if (doc['type'] == 'Token') {\n                    emit(doc._id, null);\n                  }\n                }\n" +    } +  }, +  "couchrest-hash": "541dd924551c42a2317b345effbe65cc" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/designs/users/User.json b/puppet/modules/site_couchdb/files/designs/users/User.json new file mode 100644 index 00000000..8a82cf4a --- /dev/null +++ b/puppet/modules/site_couchdb/files/designs/users/User.json @@ -0,0 +1,22 @@ +{ +  "_id": "_design/User", +  "language": "javascript", +  "views": { +    "by_login": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'User') && (doc['login'] != null)) {\n                    emit(doc['login'], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    }, +    "all": { +      "map": "                function(doc) {\n                  if (doc['type'] == 'User') {\n                    emit(doc._id, null);\n                  }\n                }\n" +    }, +    "by_created_at_and_one_month_warning_not_sent": { +      "map": "function (doc) {\n  if ((doc['type'] == 'User') && (doc['created_at'] != null) && (doc['one_month_warning_sent'] == null)) {\n    emit(doc['created_at'], 1);\n  }    \n}\n", +      "reduce": "          function(key, values, rereduce) {\n            return sum(values);\n          }\n" +    }, +    "by_created_at": { +      "map": "                function(doc) {\n                  if ((doc['type'] == 'User') && (doc['created_at'] != null)) {\n                    emit(doc['created_at'], 1);\n                  }\n                }\n", +      "reduce": "_sum" +    } +  }, +  "couchrest-hash": "d854607d299887a347e554176cb79e20" +}
\ No newline at end of file diff --git a/puppet/modules/site_couchdb/files/leap_ca_daemon b/puppet/modules/site_couchdb/files/leap_ca_daemon new file mode 100755 index 00000000..9a1a0bc7 --- /dev/null +++ b/puppet/modules/site_couchdb/files/leap_ca_daemon @@ -0,0 +1,157 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides:          leap_ca_daemon +# Required-Start:    $remote_fs $syslog +# Required-Stop:     $remote_fs $syslog +# Default-Start:     2 3 4 5 +# Default-Stop:      0 1 6 +# Short-Description: leap_ca_daemon initscript  +# Description:       Controls leap_ca_daemon (see https://github.com/leapcode/leap_ca +#                    for more information.				  +### END INIT INFO + +# Author: varac <varac@leap.se> +# + +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="leap_ca_daemon initscript" +NAME=leap_ca_daemon +DAEMON=/usr/local/bin/$NAME +DAEMON_ARGS="run " +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ +	# Return +	#   0 if daemon has been started +	#   1 if daemon was already running +	#   2 if daemon could not be started +	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ +		|| return 1 +	start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ +		$DAEMON_ARGS \ +		|| return 2 +	# Add code here, if necessary, that waits for the process to be ready +	# to handle requests from services started subsequently which depend +	# on this one.  As a last resort, sleep for some time. +} + +# +# Function that stops the daemon/service +# +do_stop() +{ +	# Return +	#   0 if daemon has been stopped +	#   1 if daemon was already stopped +	#   2 if daemon could not be stopped +	#   other if a failure occurred +	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME +	RETVAL="$?" +	[ "$RETVAL" = 2 ] && return 2 +	# Wait for children to finish too if this is a daemon that forks +	# and if the daemon is only ever run from this initscript. +	# If the above conditions are not satisfied then add some other code +	# that waits for the process to drop all resources that could be +	# needed by services started subsequently.  A last resort is to +	# sleep for some time. +	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON +	[ "$?" = 2 ] && return 2 +	# Many daemons don't delete their pidfiles when they exit. +	rm -f $PIDFILE +	return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { +	# +	# If the daemon can reload its configuration without +	# restarting (for example, when it is sent a SIGHUP), +	# then implement that here. +	# +	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME +	return 0 +} + +case "$1" in +  start) +	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" +	do_start +	case "$?" in +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; +	esac +	;; +  stop) +	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" +	do_stop +	case "$?" in +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; +	esac +	;; +  status) +	status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? +	;; +  #reload|force-reload) +	# +	# If do_reload() is not implemented then leave this commented out +	# and leave 'force-reload' as an alias for 'restart'. +	# +	#log_daemon_msg "Reloading $DESC" "$NAME" +	#do_reload +	#log_end_msg $? +	#;; +  restart|force-reload) +	# +	# If the "reload" option is implemented then remove the +	# 'force-reload' alias +	# +	log_daemon_msg "Restarting $DESC" "$NAME" +	do_stop +	case "$?" in +	  0|1) +		do_start +		case "$?" in +			0) log_end_msg 0 ;; +			1) log_end_msg 1 ;; # Old process is still running +			*) log_end_msg 1 ;; # Failed to start +		esac +		;; +	  *) +		# Failed to stop +		log_end_msg 1 +		;; +	esac +	;; +  *) +	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 +	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 +	exit 3 +	;; +esac + +: diff --git a/puppet/modules/site_couchdb/files/local.ini b/puppet/modules/site_couchdb/files/local.ini new file mode 100644 index 00000000..b921a927 --- /dev/null +++ b/puppet/modules/site_couchdb/files/local.ini @@ -0,0 +1,8 @@ +; Puppet modified file !! + +; Custom settings should be made in this file. They will override settings +; in default.ini, but unlike changes made to default.ini, this file won't be +; overwritten on server upgrade. + +[compactions] +_default = [{db_fragmentation, "70%"}, {view_fragmentation, "60%"}, {from, "03:00"}, {to, "05:00"}] diff --git a/puppet/modules/site_couchdb/files/runit_config b/puppet/modules/site_couchdb/files/runit_config new file mode 100644 index 00000000..169b4832 --- /dev/null +++ b/puppet/modules/site_couchdb/files/runit_config @@ -0,0 +1,6 @@ +#!/bin/bash +exec 2>&1 +export HOME=/home/bigcouch +ulimit -H -n 32768 +ulimit -S -n 32768 +exec chpst -u bigcouch /opt/bigcouch/bin/bigcouch diff --git a/puppet/modules/site_couchdb/lib/puppet/parser/functions/rotated_db_name.rb b/puppet/modules/site_couchdb/lib/puppet/parser/functions/rotated_db_name.rb new file mode 100644 index 00000000..6458ae81 --- /dev/null +++ b/puppet/modules/site_couchdb/lib/puppet/parser/functions/rotated_db_name.rb @@ -0,0 +1,24 @@ +module Puppet::Parser::Functions +  newfunction(:rotated_db_name, :type => :rvalue, :doc => <<-EOS +This function takes a database name string and returns a database name with the current rotation stamp appended. +The first argument is the base name of the database. Subsequent arguments may contain these options: +  * 'next'    -- return the db name for the next rotation, not the current one. +  * 'monthly' -- rotate monthly (default) +  * 'weekly'  -- rotate weekly +*Examples:* +    rotated_db_name('tokens') => 'tokens_551' +    EOS +  ) do |arguments| +    if arguments.include?('weekly') +      rotation_period = 604800 # 1 week +    else +      rotation_period = 2592000 # 1 month +    end +    suffix = Time.now.utc.to_i / rotation_period +    if arguments.include?('next') +      suffix += 1 +    end +    "#{arguments.first}_#{suffix}" +  end +end + diff --git a/puppet/modules/site_couchdb/manifests/add_users.pp b/puppet/modules/site_couchdb/manifests/add_users.pp new file mode 100644 index 00000000..c905316b --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/add_users.pp @@ -0,0 +1,57 @@ +# add couchdb users for all services +class site_couchdb::add_users { + +  Class['site_couchdb::create_dbs'] +    -> Class['site_couchdb::add_users'] + +  # Couchdb users + +  ## leap_mx couchdb user +  ## read: identities +  ## write access to user-<uuid> +  couchdb::add_user { $site_couchdb::couchdb_leap_mx_user: +    roles   => '["identities"]', +    pw      => $site_couchdb::couchdb_leap_mx_pw, +    salt    => $site_couchdb::couchdb_leap_mx_salt, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## nickserver couchdb user +  ## r: identities +  ## r/w: keycache +  couchdb::add_user { $site_couchdb::couchdb_nickserver_user: +    roles   => '["identities","keycache"]', +    pw      => $site_couchdb::couchdb_nickserver_pw, +    salt    => $site_couchdb::couchdb_nickserver_salt, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## soledad couchdb user +  ## r/w: user-<uuid>, shared +  ## read: tokens +  couchdb::add_user { $site_couchdb::couchdb_soledad_user: +    roles   => '["tokens"]', +    pw      => $site_couchdb::couchdb_soledad_pw, +    salt    => $site_couchdb::couchdb_soledad_salt, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## webapp couchdb user +  ## read/write: users, tokens, sessions, tickets, identities, customer +  couchdb::add_user { $site_couchdb::couchdb_webapp_user: +    roles   => '["tokens","identities","users"]', +    pw      => $site_couchdb::couchdb_webapp_pw, +    salt    => $site_couchdb::couchdb_webapp_salt, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## replication couchdb user +  ## read/write: all databases for replication +  couchdb::add_user { $site_couchdb::couchdb_replication_user: +    roles   => '["replication"]', +    pw      => $site_couchdb::couchdb_replication_pw, +    salt    => $site_couchdb::couchdb_replication_salt, +    require => Couchdb::Query::Setup['localhost'] +  } + +} diff --git a/puppet/modules/site_couchdb/manifests/backup.pp b/puppet/modules/site_couchdb/manifests/backup.pp new file mode 100644 index 00000000..8b5aa6ea --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/backup.pp @@ -0,0 +1,23 @@ +class site_couchdb::backup { + +  # general backupninja config +  backupninja::config { 'backupninja_config': +    usecolors     => false, +  } + +  # dump all DBs locally to /var/backups/couchdb once a day +  backupninja::sh { 'couchdb_backup': +    command_string => "cd /srv/leap/couchdb/scripts \n./couchdb_dumpall.sh" +  } + +  # Deploy /etc/leap/couchdb_scripts_defaults.conf so we can exclude +  # some databases + +  file { '/etc/leap/couchdb_scripts_defaults.conf': +    source => 'puppet:///modules/site_couchdb/couchdb_scripts_defaults.conf', +    mode   => '0644', +    owner  => 'root', +    group  => 'root', +  } + +} diff --git a/puppet/modules/site_couchdb/manifests/bigcouch.pp b/puppet/modules/site_couchdb/manifests/bigcouch.pp new file mode 100644 index 00000000..2de3d4d0 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/bigcouch.pp @@ -0,0 +1,50 @@ +# sets up bigcouch on couchdb node +class site_couchdb::bigcouch { + +  $config         = $::site_couchdb::couchdb_config['bigcouch'] +  $cookie         = $config['cookie'] +  $ednp_port      = $config['ednp_port'] + +  class { 'couchdb': +    admin_pw            => $::site_couchdb::couchdb_admin_pw, +    admin_salt          => $::site_couchdb::couchdb_admin_salt, +    bigcouch            => true, +    bigcouch_cookie     => $cookie, +    ednp_port           => $ednp_port, +    chttpd_bind_address => '127.0.0.1' +  } + +  # +  # stunnel must running correctly before bigcouch dbs can be set up. +  # +  Class['site_config::default'] +    -> Class['site_config::resolvconf'] +    -> Class['couchdb::bigcouch::package::cloudant'] +    -> Service['shorewall'] +    -> Exec['refresh_stunnel'] +    -> Class['site_couchdb::setup'] +    -> Class['site_couchdb::bigcouch::add_nodes'] +    -> Class['site_couchdb::bigcouch::settle_cluster'] +    -> Class['site_couchdb::create_dbs'] + +  include site_couchdb::bigcouch::add_nodes +  include site_couchdb::bigcouch::settle_cluster +  include site_couchdb::bigcouch::compaction + +  file { '/var/log/bigcouch': +    ensure => directory +  } + +  file { '/etc/sv/bigcouch/run': +    ensure  => present, +    source  => 'puppet:///modules/site_couchdb/runit_config', +    owner   => root, +    group   => root, +    mode    => '0755', +    require => Package['couchdb'], +    notify  => Service['couchdb'] +  } + +  include site_check_mk::agent::couchdb::bigcouch + +} diff --git a/puppet/modules/site_couchdb/manifests/bigcouch/add_nodes.pp b/puppet/modules/site_couchdb/manifests/bigcouch/add_nodes.pp new file mode 100644 index 00000000..c8c43275 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/bigcouch/add_nodes.pp @@ -0,0 +1,8 @@ +class site_couchdb::bigcouch::add_nodes { +  # loop through neighbors array and add nodes +  $nodes = $::site_couchdb::bigcouch::config['neighbors'] + +  couchdb::bigcouch::add_node { $nodes: +    require => Couchdb::Query::Setup['localhost'] +  } +} diff --git a/puppet/modules/site_couchdb/manifests/bigcouch/compaction.pp b/puppet/modules/site_couchdb/manifests/bigcouch/compaction.pp new file mode 100644 index 00000000..84aab4ef --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/bigcouch/compaction.pp @@ -0,0 +1,8 @@ +class site_couchdb::bigcouch::compaction { +  cron { +    'compact_all_shards': +      command     => '/srv/leap/couchdb/scripts/bigcouch_compact_all_shards.sh >> /var/log/bigcouch/compaction.log', +      hour        => 3, +      minute      => 17; +  } +} diff --git a/puppet/modules/site_couchdb/manifests/bigcouch/settle_cluster.pp b/puppet/modules/site_couchdb/manifests/bigcouch/settle_cluster.pp new file mode 100644 index 00000000..820b5be2 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/bigcouch/settle_cluster.pp @@ -0,0 +1,11 @@ +class site_couchdb::bigcouch::settle_cluster { + +  exec { 'wait_for_couch_nodes': +    command => '/srv/leap/bin/run_tests --test CouchDB/Are_configured_nodes_online? --retry 12 --wait 10' +  } + +  exec { 'settle_cluster_membership': +    command => '/srv/leap/bin/run_tests --test CouchDB/Is_cluster_membership_ok? --retry 12 --wait 10', +    require => Exec['wait_for_couch_nodes'] +  } +} diff --git a/puppet/modules/site_couchdb/manifests/create_dbs.pp b/puppet/modules/site_couchdb/manifests/create_dbs.pp new file mode 100644 index 00000000..a2d1c655 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/create_dbs.pp @@ -0,0 +1,102 @@ +# creates neccesary databases +class site_couchdb::create_dbs { + +  Class['site_couchdb::setup'] +    -> Class['site_couchdb::create_dbs'] + +  ### customer database +  ### r/w: webapp, +  couchdb::create_db { 'customers': +    members => "{ \"names\": [\"${site_couchdb::couchdb_webapp_user}\"], \"roles\": [\"replication\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## identities database +  ## r: nickserver, leap_mx - needs to be restrict with design document +  ## r/w: webapp +  couchdb::create_db { 'identities': +    members => "{ \"names\": [], \"roles\": [\"replication\", \"identities\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## keycache database +  ## r/w: nickserver +  couchdb::create_db { 'keycache': +    members => "{ \"names\": [], \"roles\": [\"replication\", \"keycache\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## sessions database +  ## r/w: webapp +  $sessions_db = rotated_db_name('sessions', 'monthly') +  couchdb::create_db { $sessions_db: +    members => "{ \"names\": [\"${site_couchdb::couchdb_webapp_user}\"], \"roles\": [\"replication\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  $sessions_next_db = rotated_db_name('sessions', 'monthly', 'next') +  couchdb::create_db { $sessions_next_db: +    members => "{ \"names\": [\"${site_couchdb::couchdb_webapp_user}\"], \"roles\": [\"replication\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## shared database +  ## r/w: soledad +  couchdb::create_db { 'shared': +    members => "{ \"names\": [\"${site_couchdb::couchdb_soledad_user}\"], \"roles\": [\"replication\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## tickets database +  ## r/w: webapp +  couchdb::create_db { 'tickets': +    members => "{ \"names\": [\"${site_couchdb::couchdb_webapp_user}\"], \"roles\": [\"replication\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## tokens database +  ## r: soledad - needs to be restricted with a design document +  ## r/w: webapp +  $tokens_db = rotated_db_name('tokens', 'monthly') +  couchdb::create_db { $tokens_db: +    members => "{ \"names\": [], \"roles\": [\"replication\", \"tokens\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  $tokens_next_db = rotated_db_name('tokens', 'monthly', 'next') +  couchdb::create_db { $tokens_next_db: +    members => "{ \"names\": [], \"roles\": [\"replication\", \"tokens\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## users database +  ## r/w: webapp +  couchdb::create_db { 'users': +    members => "{ \"names\": [], \"roles\": [\"replication\", \"users\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## tmp_users database +  ## r/w: webapp +  couchdb::create_db { 'tmp_users': +    members => "{ \"names\": [], \"roles\": [\"replication\", \"users\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## messages db +  ## store messages to the clients such as payment reminders +  ## r/w: webapp +  couchdb::create_db { 'messages': +    members => "{ \"names\": [\"${site_couchdb::couchdb_webapp_user}\"], \"roles\": [\"replication\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## invite_codes db +  ## store invite codes for new signups +  ## r/w: webapp +  couchdb::create_db { 'invite_codes': +    members => "{ \"names\": [\"${site_couchdb::couchdb_webapp_user}\"], \"roles\": [\"replication\"] }", +    require => Couchdb::Query::Setup['localhost'] +  } + +} diff --git a/puppet/modules/site_couchdb/manifests/designs.pp b/puppet/modules/site_couchdb/manifests/designs.pp new file mode 100644 index 00000000..e5fd94c6 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/designs.pp @@ -0,0 +1,46 @@ +class site_couchdb::designs { + +  Class['site_couchdb::create_dbs'] +    -> Class['site_couchdb::designs'] + +  file { '/srv/leap/couchdb/designs': +    ensure  => directory, +    source  => 'puppet:///modules/site_couchdb/designs', +    recurse => true, +    purge   => true, +    mode    => '0755' +  } + +  site_couchdb::upload_design { +    'customers':    design => 'customers/Customer.json'; +    'identities':   design => 'identities/Identity.json'; +    'tickets':      design => 'tickets/Ticket.json'; +    'messages':     design => 'messages/Message.json'; +    'users':        design => 'users/User.json'; +    'tmp_users':    design => 'users/User.json'; +    'invite_codes': design => 'invite_codes/InviteCode.json'; +    'shared_docs': +      db => 'shared', +      design => 'shared/docs.json'; +    'shared_syncs': +      db => 'shared', +      design => 'shared/syncs.json'; +    'shared_transactions': +      db => 'shared', +      design => 'shared/transactions.json'; +  } + +  $sessions_db      = rotated_db_name('sessions', 'monthly') +  $sessions_next_db = rotated_db_name('sessions', 'monthly', 'next') +  site_couchdb::upload_design { +    $sessions_db:       design => 'sessions/Session.json'; +    $sessions_next_db:  design => 'sessions/Session.json'; +  } + +  $tokens_db       = rotated_db_name('tokens', 'monthly') +  $tokens_next_db  = rotated_db_name('tokens', 'monthly', 'next') +  site_couchdb::upload_design { +    $tokens_db:      design => 'tokens/Token.json'; +    $tokens_next_db: design => 'tokens/Token.json'; +  } +} diff --git a/puppet/modules/site_couchdb/manifests/init.pp b/puppet/modules/site_couchdb/manifests/init.pp new file mode 100644 index 00000000..c4fe6277 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/init.pp @@ -0,0 +1,81 @@ +# entry class for configuring couchdb/bigcouch node +# couchdb node +class site_couchdb { +  tag 'leap_service' + +  $couchdb_config           = hiera('couch') +  $couchdb_users            = $couchdb_config['users'] + +  $couchdb_admin            = $couchdb_users['admin'] +  $couchdb_admin_user       = $couchdb_admin['username'] +  $couchdb_admin_pw         = $couchdb_admin['password'] +  $couchdb_admin_salt       = $couchdb_admin['salt'] + +  $couchdb_leap_mx          = $couchdb_users['leap_mx'] +  $couchdb_leap_mx_user     = $couchdb_leap_mx['username'] +  $couchdb_leap_mx_pw       = $couchdb_leap_mx['password'] +  $couchdb_leap_mx_salt     = $couchdb_leap_mx['salt'] + +  $couchdb_nickserver       = $couchdb_users['nickserver'] +  $couchdb_nickserver_user  = $couchdb_nickserver['username'] +  $couchdb_nickserver_pw    = $couchdb_nickserver['password'] +  $couchdb_nickserver_salt  = $couchdb_nickserver['salt'] + +  $couchdb_soledad          = $couchdb_users['soledad'] +  $couchdb_soledad_user     = $couchdb_soledad['username'] +  $couchdb_soledad_pw       = $couchdb_soledad['password'] +  $couchdb_soledad_salt     = $couchdb_soledad['salt'] + +  $couchdb_webapp           = $couchdb_users['webapp'] +  $couchdb_webapp_user      = $couchdb_webapp['username'] +  $couchdb_webapp_pw        = $couchdb_webapp['password'] +  $couchdb_webapp_salt      = $couchdb_webapp['salt'] + +  $couchdb_replication      = $couchdb_users['replication'] +  $couchdb_replication_user = $couchdb_replication['username'] +  $couchdb_replication_pw   = $couchdb_replication['password'] +  $couchdb_replication_salt = $couchdb_replication['salt'] + +  $couchdb_backup           = $couchdb_config['backup'] +  $couchdb_mode             = $couchdb_config['mode'] + +  # ensure bigcouch has been purged from the system: +  # TODO: remove this check in 0.9 release +  if file('/opt/bigcouch/bin/bigcouch', '/dev/null') != '' { +    fail 'ERROR: BigCouch appears to be installed. Make sure you have migrated to CouchDB before proceeding. See https://leap.se/upgrade-0-8' +  } + +  include site_couchdb::plain + +  Class['site_config::default'] +    -> Service['shorewall'] +    -> Exec['refresh_stunnel'] +    -> Class['couchdb'] +    -> Class['site_couchdb::setup'] + +  include ::site_config::default +  include site_stunnel + +  include site_couchdb::setup +  include site_couchdb::create_dbs +  include site_couchdb::add_users +  include site_couchdb::designs +  include site_couchdb::logrotate + +  if $couchdb_backup   { include site_couchdb::backup } + +  include site_check_mk::agent::couchdb + +  # remove tapicero leftovers on couchdb nodes +  include site_config::remove::tapicero + +  # Destroy every per-user storage database +  # where the corresponding user record does not exist. +  cron { 'cleanup_stale_userdbs': +    command => '(/bin/date; /srv/leap/couchdb/scripts/cleanup-user-dbs) >> /var/log/leap/couchdb-cleanup.log', +    user    => 'root', +    hour    => 4, +    minute  => 7; +  } + +} diff --git a/puppet/modules/site_couchdb/manifests/logrotate.pp b/puppet/modules/site_couchdb/manifests/logrotate.pp new file mode 100644 index 00000000..bb8843bb --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/logrotate.pp @@ -0,0 +1,14 @@ +# configure couchdb logrotation +class site_couchdb::logrotate { + +  augeas { +    'logrotate_bigcouch': +      context => '/files/etc/logrotate.d/bigcouch/rule', +      changes => [ +        'set file /opt/bigcouch/var/log/*.log', 'set rotate 7', +        'set schedule daily', 'set compress compress', +        'set missingok missingok', 'set ifempty notifempty', +        'set copytruncate copytruncate' ] +  } + +} diff --git a/puppet/modules/site_couchdb/manifests/mirror.pp b/puppet/modules/site_couchdb/manifests/mirror.pp new file mode 100644 index 00000000..fb82b897 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/mirror.pp @@ -0,0 +1,78 @@ +# configure mirroring of couch nodes +class site_couchdb::mirror { + +  Class['site_couchdb::add_users'] +    -> Class['site_couchdb::mirror'] + +  class { 'couchdb': +    admin_pw            => $site_couchdb::couchdb_admin_pw, +    admin_salt          => $site_couchdb::couchdb_admin_salt, +    chttpd_bind_address => '127.0.0.1' +  } + +  $masters = $site_couchdb::couchdb_config['replication']['masters'] +  $master_node_names = keys($site_couchdb::couchdb_config['replication']['masters']) +  $master_node = $masters[$master_node_names[0]] +  $user = $site_couchdb::couchdb_replication_user +  $password = $site_couchdb::couchdb_replication_pw +  $from_host = $master_node['domain_internal'] +  $from_port = $master_node['couch_port'] +  $from = "http://${user}:${password}@${from_host}:${from_port}" + +  notice("mirror from: ${from}") + +  ### customer database +  couchdb::mirror_db { 'customers': +    from    => $from, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## identities database +  couchdb::mirror_db { 'identities': +    from    => $from, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## keycache database +  couchdb::mirror_db { 'keycache': +    from    => $from, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## sessions database +  couchdb::mirror_db { 'sessions': +    from    => $from, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## shared database +  couchdb::mirror_db { 'shared': +    from    => $from, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## tickets database +  couchdb::mirror_db { 'tickets': +    from    => $from, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## tokens database +  couchdb::mirror_db { 'tokens': +    from    => $from, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## users database +  couchdb::mirror_db { 'users': +    from    => $from, +    require => Couchdb::Query::Setup['localhost'] +  } + +  ## messages db +  couchdb::mirror_db { 'messages': +    from    => $from, +    require => Couchdb::Query::Setup['localhost'] +  } + +} diff --git a/puppet/modules/site_couchdb/manifests/plain.pp b/puppet/modules/site_couchdb/manifests/plain.pp new file mode 100644 index 00000000..b40fc100 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/plain.pp @@ -0,0 +1,14 @@ +# this class sets up a single, plain couchdb node +class site_couchdb::plain { +  class { 'couchdb': +    admin_pw            => $site_couchdb::couchdb_admin_pw, +    admin_salt          => $site_couchdb::couchdb_admin_salt, +    chttpd_bind_address => '127.0.0.1' +  } + +  include site_check_mk::agent::couchdb::plain + +  # remove bigcouch leftovers from previous installations +  include ::site_config::remove::bigcouch + +} diff --git a/puppet/modules/site_couchdb/manifests/setup.pp b/puppet/modules/site_couchdb/manifests/setup.pp new file mode 100644 index 00000000..710d3c1c --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/setup.pp @@ -0,0 +1,61 @@ +# +# An initial setup class. All the other classes depend on this +# +class site_couchdb::setup { + +  # ensure that we don't have leftovers from previous installations +  # where we installed the cloudant bigcouch package +  # https://leap.se/code/issues/4971 +  class { 'couchdb::bigcouch::package::cloudant': +    ensure => absent +  } + +  $user = $site_couchdb::couchdb_admin_user + +  # setup /etc/couchdb/couchdb-admin.netrc for couchdb admin access +  couchdb::query::setup { 'localhost': +    user => $user, +    pw   => $site_couchdb::couchdb_admin_pw +  } + +  # We symlink /etc/couchdb/couchdb-admin.netrc to /etc/couchdb/couchdb.netrc +  # for puppet commands, and to to /root/.netrc for couchdb_scripts +  # (eg. backup) and to makes life easier for the admin on the command line +  # (i.e. using curl/wget without passing credentials) +  file { +    '/etc/couchdb/couchdb.netrc': +      ensure  => link, +      target  => "/etc/couchdb/couchdb-${user}.netrc"; +    '/root/.netrc': +      ensure  => link, +      target  => '/etc/couchdb/couchdb.netrc'; +  } + +  # setup /etc/couchdb/couchdb-soledad-admin.netrc file for couchdb admin +  # access, accessible only for the soledad-admin user to create soledad +  # userdbs +  if member(hiera('services', []), 'soledad') { +    file { '/etc/couchdb/couchdb-soledad-admin.netrc': +      content => "machine localhost login ${user} password ${site_couchdb::couchdb_admin_pw}", +      mode    => '0400', +      owner   => 'soledad-admin', +      group   => 'root', +      require => [ Package['couchdb'], User['soledad-admin'] ]; +    } +  } + +  # Checkout couchdb_scripts repo +  file { +    '/srv/leap/couchdb': +      ensure => directory +  } + +  vcsrepo { '/srv/leap/couchdb/scripts': +    ensure   => present, +    provider => git, +    source   => 'https://leap.se/git/couchdb_scripts', +    revision => 'origin/master', +    require  => File['/srv/leap/couchdb'] +  } + +} diff --git a/puppet/modules/site_couchdb/manifests/upload_design.pp b/puppet/modules/site_couchdb/manifests/upload_design.pp new file mode 100644 index 00000000..bd73ebf2 --- /dev/null +++ b/puppet/modules/site_couchdb/manifests/upload_design.pp @@ -0,0 +1,14 @@ +# upload a design doc to a db +define site_couchdb::upload_design($design, $db = $title) { +  $design_name = regsubst($design, '^.*\/(.*)\.json$', '\1') +  $id = "_design/${design_name}" +  $file = "/srv/leap/couchdb/designs/${design}" +  exec { +    "upload_design_${name}": +      command => "/usr/local/bin/couch-doc-update --host 127.0.0.1:5984 --db '${db}' --id '${id}' --data '{}' --file '${file}'", +      refreshonly => false, +      loglevel => debug, +      logoutput => on_failure, +      require => File['/srv/leap/couchdb/designs']; +  } +} diff --git a/puppet/modules/site_haproxy/files/haproxy-stats.cfg b/puppet/modules/site_haproxy/files/haproxy-stats.cfg new file mode 100644 index 00000000..e6335ba2 --- /dev/null +++ b/puppet/modules/site_haproxy/files/haproxy-stats.cfg @@ -0,0 +1,6 @@ +# provide access to stats for the nagios plugin +listen stats 127.0.0.1:8000 +    mode http +    stats enable +    stats uri /haproxy + diff --git a/puppet/modules/site_haproxy/manifests/init.pp b/puppet/modules/site_haproxy/manifests/init.pp new file mode 100644 index 00000000..b28ce80e --- /dev/null +++ b/puppet/modules/site_haproxy/manifests/init.pp @@ -0,0 +1,41 @@ +class site_haproxy { +    $haproxy     = hiera('haproxy') + +    class { 'haproxy': +      enable           => true, +      manage_service   => true, +      global_options   => { +        'log'     => '127.0.0.1 local0', +        'maxconn' => '4096', +        'stats'   => 'socket /var/run/haproxy.sock user haproxy group haproxy', +        'chroot'  => '/usr/share/haproxy', +        'user'    => 'haproxy', +        'group'   => 'haproxy', +        'daemon'  => '' +      }, +      defaults_options => { +        'log'             => 'global', +        'retries'         => '3', +        'option'          => 'redispatch', +        'timeout connect' => '4000', +        'timeout client'  => '20000', +        'timeout server'  => '20000' +      } +  } + +  # monitor haproxy +  concat::fragment { 'stats': +    target => '/etc/haproxy/haproxy.cfg', +    order  => '90', +    source => 'puppet:///modules/site_haproxy/haproxy-stats.cfg'; +  } + +  # Template uses $haproxy +  concat::fragment { 'leap_haproxy_webapp_couchdb': +    target  => '/etc/haproxy/haproxy.cfg', +    order   => '20', +    content => template('site_haproxy/haproxy.cfg.erb'), +  } + +  include site_check_mk::agent::haproxy +} diff --git a/puppet/modules/site_haproxy/templates/couch.erb b/puppet/modules/site_haproxy/templates/couch.erb new file mode 100644 index 00000000..f42e8368 --- /dev/null +++ b/puppet/modules/site_haproxy/templates/couch.erb @@ -0,0 +1,32 @@ +frontend couch +  bind localhost:<%= @listen_port %> +  mode     http +  option   httplog +  option   dontlognull +  option   http-server-close    # use client keep-alive, but close server connection. +  use_backend couch_read if METH_GET +  default_backend couch_write + +backend couch_write +  mode http +  balance  roundrobin +  option   httpchk GET /        # health check using simple get to root +  option   allbackups           # balance among all backups, not just one. +  default-server inter 3000 fastinter 1000 downinter 1000 rise 2 fall 1 +<%- @servers.sort.each do |name,server| -%> +<%-   next unless server['writable'] -%> +    # <%=name%> +    server couchdb_<%=server['port']%> <%=server['host']%>:<%=server['port']%> <%='backup' if server['backup']%> weight <%=server['weight']%> check +<%- end -%> + +backend couch_read +  mode http +  balance  roundrobin +  option   httpchk GET /        # health check using simple get to root +  option   allbackups           # balance among all backups, not just one. +  default-server inter 3000 fastinter 1000 downinter 1000 rise 2 fall 1 +<%- @servers.sort.each do |name,server| -%> +    # <%=name%> +    server couchdb_<%=server['port']%> <%=server['host']%>:<%=server['port']%> <%='backup' if server['backup']%> weight <%=server['weight']%> check +<%- end -%> + diff --git a/puppet/modules/site_haproxy/templates/haproxy.cfg.erb b/puppet/modules/site_haproxy/templates/haproxy.cfg.erb new file mode 100644 index 00000000..8311b1a5 --- /dev/null +++ b/puppet/modules/site_haproxy/templates/haproxy.cfg.erb @@ -0,0 +1,11 @@ +<%- @haproxy.each do |frontend, options| -%> +<%-   if options['servers'] -%> + +## +## <%= frontend %> +## + +<%=     scope.function_templatewlv(["site_haproxy/#{frontend}.erb", options]) %> +<%-   end -%> +<%- end -%> + diff --git a/puppet/modules/site_mx/manifests/init.pp b/puppet/modules/site_mx/manifests/init.pp new file mode 100644 index 00000000..a9b0198b --- /dev/null +++ b/puppet/modules/site_mx/manifests/init.pp @@ -0,0 +1,20 @@ +class site_mx { +  tag 'leap_service' +  Class['site_config::default'] -> Class['site_mx'] + +  include site_config::default +  include site_config::x509::cert +  include site_config::x509::key +  include site_config::x509::ca +  include site_config::x509::client_ca::ca +  include site_config::x509::client_ca::key + +  include site_stunnel + +  include site_postfix::mx +  include site_haproxy +  include site_shorewall::mx +  include site_shorewall::service::smtp +  include leap_mx +  include site_check_mk::agent::mx +} diff --git a/puppet/modules/site_nagios/files/configs/Debian/nagios.cfg b/puppet/modules/site_nagios/files/configs/Debian/nagios.cfg new file mode 100644 index 00000000..62f26f2c --- /dev/null +++ b/puppet/modules/site_nagios/files/configs/Debian/nagios.cfg @@ -0,0 +1,1302 @@ +############################################################################## +# +# NAGIOS.CFG - Sample Main Config File for Nagios +# +# +############################################################################## + + +# LOG FILE +# This is the main log file where service and host events are logged +# for historical purposes.  This should be the first option specified +# in the config file!!! + +log_file=/var/log/nagios3/nagios.log + + + +# OBJECT CONFIGURATION FILE(S) +# These are the object configuration files in which you define hosts, +# host groups, contacts, contact groups, services, etc. +# You can split your object definitions across several config files +# if you wish (as shown below), or keep them all in a single config file. +#cfg_file=/etc/nagios3/commands.cfg + +# Check_mk configuration files +cfg_dir=/etc/nagios3/conf.d/check_mk +cfg_dir=/etc/nagios3/local + +# Puppet-managed configuration files +cfg_file=/etc/nagios3/nagios_templates.cfg +cfg_file=/etc/nagios3/nagios_command.cfg +cfg_file=/etc/nagios3/nagios_contact.cfg +cfg_file=/etc/nagios3/nagios_contactgroup.cfg +cfg_file=/etc/nagios3/nagios_host.cfg +cfg_file=/etc/nagios3/nagios_hostdependency.cfg +cfg_file=/etc/nagios3/nagios_hostescalation.cfg +cfg_file=/etc/nagios3/nagios_hostextinfo.cfg +cfg_file=/etc/nagios3/nagios_hostgroup.cfg +cfg_file=/etc/nagios3/nagios_hostgroupescalation.cfg +cfg_file=/etc/nagios3/nagios_service.cfg +cfg_file=/etc/nagios3/nagios_servicedependency.cfg +cfg_file=/etc/nagios3/nagios_serviceescalation.cfg +cfg_file=/etc/nagios3/nagios_serviceextinfo.cfg +cfg_file=/etc/nagios3/nagios_servicegroup.cfg +cfg_file=/etc/nagios3/nagios_timeperiod.cfg + +# Debian also defaults to using the check commands defined by the debian +# nagios-plugins package +cfg_dir=/etc/nagios-plugins/config + + +# OBJECT CACHE FILE +# This option determines where object definitions are cached when +# Nagios starts/restarts.  The CGIs read object definitions from +# this cache file (rather than looking at the object config files +# directly) in order to prevent inconsistencies that can occur +# when the config files are modified after Nagios starts. + +object_cache_file=/var/cache/nagios3/objects.cache + + + +# PRE-CACHED OBJECT FILE +# This options determines the location of the precached object file. +# If you run Nagios with the -p command line option, it will preprocess +# your object configuration file(s) and write the cached config to this +# file.  You can then start Nagios with the -u option to have it read +# object definitions from this precached file, rather than the standard +# object configuration files (see the cfg_file and cfg_dir options above). +# Using a precached object file can speed up the time needed to (re)start +# the Nagios process if you've got a large and/or complex configuration. +# Read the documentation section on optimizing Nagios to find our more +# about how this feature works. + +precached_object_file=/var/lib/nagios3/objects.precache + + + +# RESOURCE FILE +# This is an optional resource file that contains $USERx$ macro +# definitions. Multiple resource files can be specified by using +# multiple resource_file definitions.  The CGIs will not attempt to +# read the contents of resource files, so information that is +# considered to be sensitive (usernames, passwords, etc) can be +# defined as macros in this file and restrictive permissions (600) +# can be placed on this file. + +resource_file=/etc/nagios3/resource.cfg + + + +# STATUS FILE +# This is where the current status of all monitored services and +# hosts is stored.  Its contents are read and processed by the CGIs. +# The contents of the status file are deleted every time Nagios +#  restarts. + +status_file=/var/cache/nagios3/status.dat + + + +# STATUS FILE UPDATE INTERVAL +# This option determines the frequency (in seconds) that +# Nagios will periodically dump program, host, and +# service status data. + +status_update_interval=10 + + + +# NAGIOS USER +# This determines the effective user that Nagios should run as. +# You can either supply a username or a UID. + +nagios_user=nagios + + + +# NAGIOS GROUP +# This determines the effective group that Nagios should run as. +# You can either supply a group name or a GID. + +nagios_group=nagios + + + +# EXTERNAL COMMAND OPTION +# This option allows you to specify whether or not Nagios should check +# for external commands (in the command file defined below).  By default +# Nagios will *not* check for external commands, just to be on the +# cautious side.  If you want to be able to use the CGI command interface +# you will have to enable this. +# Values: 0 = disable commands, 1 = enable commands + +check_external_commands=1 + + + +# EXTERNAL COMMAND CHECK INTERVAL +# This is the interval at which Nagios should check for external commands. +# This value works of the interval_length you specify later.  If you leave +# that at its default value of 60 (seconds), a value of 1 here will cause +# Nagios to check for external commands every minute.  If you specify a +# number followed by an "s" (i.e. 15s), this will be interpreted to mean +# actual seconds rather than a multiple of the interval_length variable. +# Note: In addition to reading the external command file at regularly +# scheduled intervals, Nagios will also check for external commands after +# event handlers are executed. +# NOTE: Setting this value to -1 causes Nagios to check the external +# command file as often as possible. + +#command_check_interval=15s +command_check_interval=-1 + + + +# EXTERNAL COMMAND FILE +# This is the file that Nagios checks for external command requests. +# It is also where the command CGI will write commands that are submitted +# by users, so it must be writeable by the user that the web server +# is running as (usually 'nobody').  Permissions should be set at the +# directory level instead of on the file, as the file is deleted every +# time its contents are processed. +# Debian Users: In case you didn't read README.Debian yet, _NOW_ is the +# time to do it. + +command_file=/var/lib/nagios3/rw/nagios.cmd + + + +# EXTERNAL COMMAND BUFFER SLOTS +# This settings is used to tweak the number of items or "slots" that +# the Nagios daemon should allocate to the buffer that holds incoming +# external commands before they are processed.  As external commands +# are processed by the daemon, they are removed from the buffer. + +external_command_buffer_slots=4096 + + + +# LOCK FILE +# This is the lockfile that Nagios will use to store its PID number +# in when it is running in daemon mode. + +lock_file=/var/run/nagios3/nagios3.pid + + + +# TEMP FILE +# This is a temporary file that is used as scratch space when Nagios +# updates the status log, cleans the comment file, etc.  This file +# is created, used, and deleted throughout the time that Nagios is +# running. + +temp_file=/var/cache/nagios3/nagios.tmp + + + +# TEMP PATH +# This is path where Nagios can create temp files for service and +# host check results, etc. + +temp_path=/tmp + + + +# EVENT BROKER OPTIONS +# Controls what (if any) data gets sent to the event broker. +# Values:  0      = Broker nothing +#         -1      = Broker everything +#         <other> = See documentation + +event_broker_options=-1 + + + +# EVENT BROKER MODULE(S) +# This directive is used to specify an event broker module that should +# by loaded by Nagios at startup.  Use multiple directives if you want +# to load more than one module.  Arguments that should be passed to +# the module at startup are seperated from the module path by a space. +# +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING +#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +# +# Do NOT overwrite modules while they are being used by Nagios or Nagios +# will crash in a fiery display of SEGFAULT glory.  This is a bug/limitation +# either in dlopen(), the kernel, and/or the filesystem.  And maybe Nagios... +# +# The correct/safe way of updating a module is by using one of these methods: +#    1. Shutdown Nagios, replace the module file, restart Nagios +#    2. Delete the original module file, move the new module file into place, restart Nagios +# +# Example: +# +#   broker_module=<modulepath> [moduleargs] + +#broker_module=/somewhere/module1.o +#broker_module=/somewhere/module2.o arg1 arg2=3 debug=0 + + + +# LOG ROTATION METHOD +# This is the log rotation method that Nagios should use to rotate +# the main log file. Values are as follows.. +#	n	= None - don't rotate the log +#	h	= Hourly rotation (top of the hour) +#	d	= Daily rotation (midnight every day) +#	w	= Weekly rotation (midnight on Saturday evening) +#	m	= Monthly rotation (midnight last day of month) + +log_rotation_method=n + + + +# LOG ARCHIVE PATH +# This is the directory where archived (rotated) log files should be +# placed (assuming you've chosen to do log rotation). + +log_archive_path=/var/log/nagios3/archives + + + +# LOGGING OPTIONS +# If you want messages logged to the syslog facility, as well as the +# Nagios log file set this option to 1.  If not, set it to 0. + +use_syslog=0 + + + +# NOTIFICATION LOGGING OPTION +# If you don't want notifications to be logged, set this value to 0. +# If notifications should be logged, set the value to 1. + +log_notifications=1 + + + +# SERVICE RETRY LOGGING OPTION +# If you don't want service check retries to be logged, set this value +# to 0.  If retries should be logged, set the value to 1. + +log_service_retries=1 + + + +# HOST RETRY LOGGING OPTION +# If you don't want host check retries to be logged, set this value to +# 0.  If retries should be logged, set the value to 1. + +log_host_retries=1 + + + +# EVENT HANDLER LOGGING OPTION +# If you don't want host and service event handlers to be logged, set +# this value to 0.  If event handlers should be logged, set the value +# to 1. + +log_event_handlers=1 + + + +# INITIAL STATES LOGGING OPTION +# If you want Nagios to log all initial host and service states to +# the main log file (the first time the service or host is checked) +# you can enable this option by setting this value to 1.  If you +# are not using an external application that does long term state +# statistics reporting, you do not need to enable this option.  In +# this case, set the value to 0. + +log_initial_states=0 + + + +# EXTERNAL COMMANDS LOGGING OPTION +# If you don't want Nagios to log external commands, set this value +# to 0.  If external commands should be logged, set this value to 1. +# Note: This option does not include logging of passive service +# checks - see the option below for controlling whether or not +# passive checks are logged. + +log_external_commands=1 + + + +# PASSIVE CHECKS LOGGING OPTION +# If you don't want Nagios to log passive host and service checks, set +# this value to 0.  If passive checks should be logged, set +# this value to 1. + +log_passive_checks=1 + + + +# GLOBAL HOST AND SERVICE EVENT HANDLERS +# These options allow you to specify a host and service event handler +# command that is to be run for every host or service state change. +# The global event handler is executed immediately prior to the event +# handler that you have optionally specified in each host or +# service definition. The command argument is the short name of a +# command definition that you define in your host configuration file. +# Read the HTML docs for more information. + +#global_host_event_handler=somecommand +#global_service_event_handler=somecommand + + + +# SERVICE INTER-CHECK DELAY METHOD +# This is the method that Nagios should use when initially +# "spreading out" service checks when it starts monitoring.  The +# default is to use smart delay calculation, which will try to +# space all service checks out evenly to minimize CPU load. +# Using the dumb setting will cause all checks to be scheduled +# at the same time (with no delay between them)!  This is not a +# good thing for production, but is useful when testing the +# parallelization functionality. +#	n	= None - don't use any delay between checks +#	d	= Use a "dumb" delay of 1 second between checks +#	s	= Use "smart" inter-check delay calculation +#       x.xx    = Use an inter-check delay of x.xx seconds + +service_inter_check_delay_method=s + + + +# MAXIMUM SERVICE CHECK SPREAD +# This variable determines the timeframe (in minutes) from the +# program start time that an initial check of all services should +# be completed.  Default is 30 minutes. + +max_service_check_spread=30 + + + +# SERVICE CHECK INTERLEAVE FACTOR +# This variable determines how service checks are interleaved. +# Interleaving the service checks allows for a more even +# distribution of service checks and reduced load on remote +# hosts.  Setting this value to 1 is equivalent to how versions +# of Nagios previous to 0.0.5 did service checks.  Set this +# value to s (smart) for automatic calculation of the interleave +# factor unless you have a specific reason to change it. +#       s       = Use "smart" interleave factor calculation +#       x       = Use an interleave factor of x, where x is a +#                 number greater than or equal to 1. + +service_interleave_factor=s + + + +# HOST INTER-CHECK DELAY METHOD +# This is the method that Nagios should use when initially +# "spreading out" host checks when it starts monitoring.  The +# default is to use smart delay calculation, which will try to +# space all host checks out evenly to minimize CPU load. +# Using the dumb setting will cause all checks to be scheduled +# at the same time (with no delay between them)! +#	n	= None - don't use any delay between checks +#	d	= Use a "dumb" delay of 1 second between checks +#	s	= Use "smart" inter-check delay calculation +#       x.xx    = Use an inter-check delay of x.xx seconds + +host_inter_check_delay_method=s + + + +# MAXIMUM HOST CHECK SPREAD +# This variable determines the timeframe (in minutes) from the +# program start time that an initial check of all hosts should +# be completed.  Default is 30 minutes. + +max_host_check_spread=30 + + + +# MAXIMUM CONCURRENT SERVICE CHECKS +# This option allows you to specify the maximum number of +# service checks that can be run in parallel at any given time. +# Specifying a value of 1 for this variable essentially prevents +# any service checks from being parallelized.  A value of 0 +# will not restrict the number of concurrent checks that are +# being executed. + +max_concurrent_checks=0 + + + +# HOST AND SERVICE CHECK REAPER FREQUENCY +# This is the frequency (in seconds!) that Nagios will process +# the results of host and service checks. + +check_result_reaper_frequency=10 + + + + +# MAX CHECK RESULT REAPER TIME +# This is the max amount of time (in seconds) that  a single +# check result reaper event will be allowed to run before +# returning control back to Nagios so it can perform other +# duties. + +max_check_result_reaper_time=30 + + + + +# CHECK RESULT PATH +# This is directory where Nagios stores the results of host and +# service checks that have not yet been processed. +# +# Note: Make sure that only one instance of Nagios has access +# to this directory! + +check_result_path=/var/lib/nagios3/spool/checkresults + + + + +# MAX CHECK RESULT FILE AGE +# This option determines the maximum age (in seconds) which check +# result files are considered to be valid.  Files older than this +# threshold will be mercilessly deleted without further processing. + +max_check_result_file_age=3600 + + + + +# CACHED HOST CHECK HORIZON +# This option determines the maximum amount of time (in seconds) +# that the state of a previous host check is considered current. +# Cached host states (from host checks that were performed more +# recently that the timeframe specified by this value) can immensely +# improve performance in regards to the host check logic. +# Too high of a value for this option may result in inaccurate host +# states being used by Nagios, while a lower value may result in a +# performance hit for host checks.  Use a value of 0 to disable host +# check caching. + +cached_host_check_horizon=15 + + + +# CACHED SERVICE CHECK HORIZON +# This option determines the maximum amount of time (in seconds) +# that the state of a previous service check is considered current. +# Cached service states (from service checks that were performed more +# recently that the timeframe specified by this value) can immensely +# improve performance in regards to predictive dependency checks. +# Use a value of 0 to disable service check caching. + +cached_service_check_horizon=15 + + + +# ENABLE PREDICTIVE HOST DEPENDENCY CHECKS +# This option determines whether or not Nagios will attempt to execute +# checks of hosts when it predicts that future dependency logic test +# may be needed.  These predictive checks can help ensure that your +# host dependency logic works well. +# Values: +#  0 = Disable predictive checks +#  1 = Enable predictive checks (default) + +enable_predictive_host_dependency_checks=1 + + + +# ENABLE PREDICTIVE SERVICE DEPENDENCY CHECKS +# This option determines whether or not Nagios will attempt to execute +# checks of service when it predicts that future dependency logic test +# may be needed.  These predictive checks can help ensure that your +# service dependency logic works well. +# Values: +#  0 = Disable predictive checks +#  1 = Enable predictive checks (default) + +enable_predictive_service_dependency_checks=1 + + + +# SOFT STATE DEPENDENCIES +# This option determines whether or not Nagios will use soft state +# information when checking host and service dependencies. Normally +# Nagios will only use the latest hard host or service state when +# checking dependencies. If you want it to use the latest state (regardless +# of whether its a soft or hard state type), enable this option. +# Values: +#  0 = Don't use soft state dependencies (default) +#  1 = Use soft state dependencies + +soft_state_dependencies=0 + + + +# TIME CHANGE ADJUSTMENT THRESHOLDS +# These options determine when Nagios will react to detected changes +# in system time (either forward or backwards). + +#time_change_threshold=900 + + + +# AUTO-RESCHEDULING OPTION +# This option determines whether or not Nagios will attempt to +# automatically reschedule active host and service checks to +# "smooth" them out over time.  This can help balance the load on +# the monitoring server. +# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE +# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY + +auto_reschedule_checks=0 + + + +# AUTO-RESCHEDULING INTERVAL +# This option determines how often (in seconds) Nagios will +# attempt to automatically reschedule checks.  This option only +# has an effect if the auto_reschedule_checks option is enabled. +# Default is 30 seconds. +# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE +# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY + +auto_rescheduling_interval=30 + + + +# AUTO-RESCHEDULING WINDOW +# This option determines the "window" of time (in seconds) that +# Nagios will look at when automatically rescheduling checks. +# Only host and service checks that occur in the next X seconds +# (determined by this variable) will be rescheduled. This option +# only has an effect if the auto_reschedule_checks option is +# enabled.  Default is 180 seconds (3 minutes). +# WARNING: THIS IS AN EXPERIMENTAL FEATURE - IT CAN DEGRADE +# PERFORMANCE, RATHER THAN INCREASE IT, IF USED IMPROPERLY + +auto_rescheduling_window=180 + + + +# SLEEP TIME +# This is the number of seconds to sleep between checking for system +# events and service checks that need to be run. + +sleep_time=0.25 + + + +# TIMEOUT VALUES +# These options control how much time Nagios will allow various +# types of commands to execute before killing them off.  Options +# are available for controlling maximum time allotted for +# service checks, host checks, event handlers, notifications, the +# ocsp command, and performance data commands.  All values are in +# seconds. + +service_check_timeout=60 +host_check_timeout=30 +event_handler_timeout=30 +notification_timeout=30 +ocsp_timeout=5 +perfdata_timeout=5 + + + +# RETAIN STATE INFORMATION +# This setting determines whether or not Nagios will save state +# information for services and hosts before it shuts down.  Upon +# startup Nagios will reload all saved service and host state +# information before starting to monitor.  This is useful for +# maintaining long-term data on state statistics, etc, but will +# slow Nagios down a bit when it (re)starts.  Since its only +# a one-time penalty, I think its well worth the additional +# startup delay. + +retain_state_information=1 + + + +# STATE RETENTION FILE +# This is the file that Nagios should use to store host and +# service state information before it shuts down.  The state +# information in this file is also read immediately prior to +# starting to monitor the network when Nagios is restarted. +# This file is used only if the preserve_state_information +# variable is set to 1. + +state_retention_file=/var/lib/nagios3/retention.dat + + + +# RETENTION DATA UPDATE INTERVAL +# This setting determines how often (in minutes) that Nagios +# will automatically save retention data during normal operation. +# If you set this value to 0, Nagios will not save retention +# data at regular interval, but it will still save retention +# data before shutting down or restarting.  If you have disabled +# state retention, this option has no effect. + +retention_update_interval=60 + + + +# USE RETAINED PROGRAM STATE +# This setting determines whether or not Nagios will set +# program status variables based on the values saved in the +# retention file.  If you want to use retained program status +# information, set this value to 1.  If not, set this value +# to 0. + +use_retained_program_state=1 + + + +# USE RETAINED SCHEDULING INFO +# This setting determines whether or not Nagios will retain +# the scheduling info (next check time) for hosts and services +# based on the values saved in the retention file.  If you +# If you want to use retained scheduling info, set this +# value to 1.  If not, set this value to 0. + +use_retained_scheduling_info=1 + + + +# RETAINED ATTRIBUTE MASKS (ADVANCED FEATURE) +# The following variables are used to specify specific host and +# service attributes that should *not* be retained by Nagios during +# program restarts. +# +# The values of the masks are bitwise ANDs of values specified +# by the "MODATTR_" definitions found in include/common.h. +# For example, if you do not want the current enabled/disabled state +# of flap detection and event handlers for hosts to be retained, you +# would use a value of 24 for the host attribute mask... +# MODATTR_EVENT_HANDLER_ENABLED (8) + MODATTR_FLAP_DETECTION_ENABLED (16) = 24 + +# This mask determines what host attributes are not retained +retained_host_attribute_mask=0 + +# This mask determines what service attributes are not retained +retained_service_attribute_mask=0 + +# These two masks determine what process attributes are not retained. +# There are two masks, because some process attributes have host and service +# options.  For example, you can disable active host checks, but leave active +# service checks enabled. +retained_process_host_attribute_mask=0 +retained_process_service_attribute_mask=0 + +# These two masks determine what contact attributes are not retained. +# There are two masks, because some contact attributes have host and +# service options.  For example, you can disable host notifications for +# a contact, but leave service notifications enabled for them. +retained_contact_host_attribute_mask=0 +retained_contact_service_attribute_mask=0 + + + +# INTERVAL LENGTH +# This is the seconds per unit interval as used in the +# host/contact/service configuration files.  Setting this to 60 means +# that each interval is one minute long (60 seconds).  Other settings +# have not been tested much, so your mileage is likely to vary... + +interval_length=60 + + + +# AGGRESSIVE HOST CHECKING OPTION +# If you don't want to turn on aggressive host checking features, set +# this value to 0 (the default).  Otherwise set this value to 1 to +# enable the aggressive check option.  Read the docs for more info +# on what aggressive host check is or check out the source code in +# base/checks.c + +use_aggressive_host_checking=0 + + + +# SERVICE CHECK EXECUTION OPTION +# This determines whether or not Nagios will actively execute +# service checks when it initially starts.  If this option is +# disabled, checks are not actively made, but Nagios can still +# receive and process passive check results that come in.  Unless +# you're implementing redundant hosts or have a special need for +# disabling the execution of service checks, leave this enabled! +# Values: 1 = enable checks, 0 = disable checks + +execute_service_checks=1 + + + +# PASSIVE SERVICE CHECK ACCEPTANCE OPTION +# This determines whether or not Nagios will accept passive +# service checks results when it initially (re)starts. +# Values: 1 = accept passive checks, 0 = reject passive checks + +accept_passive_service_checks=1 + + + +# HOST CHECK EXECUTION OPTION +# This determines whether or not Nagios will actively execute +# host checks when it initially starts.  If this option is +# disabled, checks are not actively made, but Nagios can still +# receive and process passive check results that come in.  Unless +# you're implementing redundant hosts or have a special need for +# disabling the execution of host checks, leave this enabled! +# Values: 1 = enable checks, 0 = disable checks + +execute_host_checks=1 + + + +# PASSIVE HOST CHECK ACCEPTANCE OPTION +# This determines whether or not Nagios will accept passive +# host checks results when it initially (re)starts. +# Values: 1 = accept passive checks, 0 = reject passive checks + +accept_passive_host_checks=1 + + + +# NOTIFICATIONS OPTION +# This determines whether or not Nagios will sent out any host or +# service notifications when it is initially (re)started. +# Values: 1 = enable notifications, 0 = disable notifications + +enable_notifications=1 + + + +# EVENT HANDLER USE OPTION +# This determines whether or not Nagios will run any host or +# service event handlers when it is initially (re)started.  Unless +# you're implementing redundant hosts, leave this option enabled. +# Values: 1 = enable event handlers, 0 = disable event handlers + +enable_event_handlers=1 + + + +# PROCESS PERFORMANCE DATA OPTION +# This determines whether or not Nagios will process performance +# data returned from service and host checks.  If this option is +# enabled, host performance data will be processed using the +# host_perfdata_command (defined below) and service performance +# data will be processed using the service_perfdata_command (also +# defined below).  Read the HTML docs for more information on +# performance data. +# Values: 1 = process performance data, 0 = do not process performance data + +process_performance_data=0 + + + +# HOST AND SERVICE PERFORMANCE DATA PROCESSING COMMANDS +# These commands are run after every host and service check is +# performed.  These commands are executed only if the +# enable_performance_data option (above) is set to 1.  The command +# argument is the short name of a command definition that you +# define in your host configuration file.  Read the HTML docs for +# more information on performance data. + +#host_perfdata_command=process-host-perfdata +#service_perfdata_command=process-service-perfdata + + + +# HOST AND SERVICE PERFORMANCE DATA FILES +# These files are used to store host and service performance data. +# Performance data is only written to these files if the +# enable_performance_data option (above) is set to 1. + +#host_perfdata_file=/tmp/host-perfdata +#service_perfdata_file=/tmp/service-perfdata + + + +# HOST AND SERVICE PERFORMANCE DATA FILE TEMPLATES +# These options determine what data is written (and how) to the +# performance data files.  The templates may contain macros, special +# characters (\t for tab, \r for carriage return, \n for newline) +# and plain text.  A newline is automatically added after each write +# to the performance data file.  Some examples of what you can do are +# shown below. + +#host_perfdata_file_template=[HOSTPERFDATA]\t$TIMET$\t$HOSTNAME$\t$HOSTEXECUTIONTIME$\t$HOSTOUTPUT$\t$HOSTPERFDATA$ +#service_perfdata_file_template=[SERVICEPERFDATA]\t$TIMET$\t$HOSTNAME$\t$SERVICEDESC$\t$SERVICEEXECUTIONTIME$\t$SERVICELATENCY$\t$SERVICEOUTPUT$\t$SERVICEPERFDATA$ + + + +# HOST AND SERVICE PERFORMANCE DATA FILE MODES +# This option determines whether or not the host and service +# performance data files are opened in write ("w") or append ("a") +# mode. If you want to use named pipes, you should use the special +# pipe ("p") mode which avoid blocking at startup, otherwise you will +# likely want the defult append ("a") mode. + +#host_perfdata_file_mode=a +#service_perfdata_file_mode=a + + + +# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING INTERVAL +# These options determine how often (in seconds) the host and service +# performance data files are processed using the commands defined +# below.  A value of 0 indicates the files should not be periodically +# processed. + +#host_perfdata_file_processing_interval=0 +#service_perfdata_file_processing_interval=0 + + + +# HOST AND SERVICE PERFORMANCE DATA FILE PROCESSING COMMANDS +# These commands are used to periodically process the host and +# service performance data files.  The interval at which the +# processing occurs is determined by the options above. + +#host_perfdata_file_processing_command=process-host-perfdata-file +#service_perfdata_file_processing_command=process-service-perfdata-file + + + +# OBSESS OVER SERVICE CHECKS OPTION +# This determines whether or not Nagios will obsess over service +# checks and run the ocsp_command defined below.  Unless you're +# planning on implementing distributed monitoring, do not enable +# this option.  Read the HTML docs for more information on +# implementing distributed monitoring. +# Values: 1 = obsess over services, 0 = do not obsess (default) + +obsess_over_services=0 + + + +# OBSESSIVE COMPULSIVE SERVICE PROCESSOR COMMAND +# This is the command that is run for every service check that is +# processed by Nagios.  This command is executed only if the +# obsess_over_services option (above) is set to 1.  The command +# argument is the short name of a command definition that you +# define in your host configuration file. Read the HTML docs for +# more information on implementing distributed monitoring. + +#ocsp_command=somecommand + + + +# OBSESS OVER HOST CHECKS OPTION +# This determines whether or not Nagios will obsess over host +# checks and run the ochp_command defined below.  Unless you're +# planning on implementing distributed monitoring, do not enable +# this option.  Read the HTML docs for more information on +# implementing distributed monitoring. +# Values: 1 = obsess over hosts, 0 = do not obsess (default) + +obsess_over_hosts=0 + + + +# OBSESSIVE COMPULSIVE HOST PROCESSOR COMMAND +# This is the command that is run for every host check that is +# processed by Nagios.  This command is executed only if the +# obsess_over_hosts option (above) is set to 1.  The command +# argument is the short name of a command definition that you +# define in your host configuration file. Read the HTML docs for +# more information on implementing distributed monitoring. + +#ochp_command=somecommand + + + +# TRANSLATE PASSIVE HOST CHECKS OPTION +# This determines whether or not Nagios will translate +# DOWN/UNREACHABLE passive host check results into their proper +# state for this instance of Nagios.  This option is useful +# if you have distributed or failover monitoring setup.  In +# these cases your other Nagios servers probably have a different +# "view" of the network, with regards to the parent/child relationship +# of hosts.  If a distributed monitoring server thinks a host +# is DOWN, it may actually be UNREACHABLE from the point of +# this Nagios instance.  Enabling this option will tell Nagios +# to translate any DOWN or UNREACHABLE host states it receives +# passively into the correct state from the view of this server. +# Values: 1 = perform translation, 0 = do not translate (default) + +translate_passive_host_checks=0 + + + +# PASSIVE HOST CHECKS ARE SOFT OPTION +# This determines whether or not Nagios will treat passive host +# checks as being HARD or SOFT.  By default, a passive host check +# result will put a host into a HARD state type.  This can be changed +# by enabling this option. +# Values: 0 = passive checks are HARD, 1 = passive checks are SOFT + +passive_host_checks_are_soft=0 + + + +# ORPHANED HOST/SERVICE CHECK OPTIONS +# These options determine whether or not Nagios will periodically +# check for orphaned host service checks.  Since service checks are +# not rescheduled until the results of their previous execution +# instance are processed, there exists a possibility that some +# checks may never get rescheduled.  A similar situation exists for +# host checks, although the exact scheduling details differ a bit +# from service checks.  Orphaned checks seem to be a rare +# problem and should not happen under normal circumstances. +# If you have problems with service checks never getting +# rescheduled, make sure you have orphaned service checks enabled. +# Values: 1 = enable checks, 0 = disable checks + +check_for_orphaned_services=1 +check_for_orphaned_hosts=1 + + + +# SERVICE FRESHNESS CHECK OPTION +# This option determines whether or not Nagios will periodically +# check the "freshness" of service results.  Enabling this option +# is useful for ensuring passive checks are received in a timely +# manner. +# Values: 1 = enabled freshness checking, 0 = disable freshness checking + +check_service_freshness=1 + + + +# SERVICE FRESHNESS CHECK INTERVAL +# This setting determines how often (in seconds) Nagios will +# check the "freshness" of service check results.  If you have +# disabled service freshness checking, this option has no effect. + +service_freshness_check_interval=60 + + + +# HOST FRESHNESS CHECK OPTION +# This option determines whether or not Nagios will periodically +# check the "freshness" of host results.  Enabling this option +# is useful for ensuring passive checks are received in a timely +# manner. +# Values: 1 = enabled freshness checking, 0 = disable freshness checking + +check_host_freshness=0 + + + +# HOST FRESHNESS CHECK INTERVAL +# This setting determines how often (in seconds) Nagios will +# check the "freshness" of host check results.  If you have +# disabled host freshness checking, this option has no effect. + +host_freshness_check_interval=60 + + + + +# ADDITIONAL FRESHNESS THRESHOLD LATENCY +# This setting determines the number of seconds that Nagios +# will add to any host and service freshness thresholds that +# it calculates (those not explicitly specified by the user). + +additional_freshness_latency=15 + + + + +# FLAP DETECTION OPTION +# This option determines whether or not Nagios will try +# and detect hosts and services that are "flapping". +# Flapping occurs when a host or service changes between +# states too frequently.  When Nagios detects that a +# host or service is flapping, it will temporarily suppress +# notifications for that host/service until it stops +# flapping.  Flap detection is very experimental, so read +# the HTML documentation before enabling this feature! +# Values: 1 = enable flap detection +#         0 = disable flap detection (default) + +enable_flap_detection=1 + + + +# FLAP DETECTION THRESHOLDS FOR HOSTS AND SERVICES +# Read the HTML documentation on flap detection for +# an explanation of what this option does.  This option +# has no effect if flap detection is disabled. + +low_service_flap_threshold=5.0 +high_service_flap_threshold=20.0 +low_host_flap_threshold=5.0 +high_host_flap_threshold=20.0 + + + +# DATE FORMAT OPTION +# This option determines how short dates are displayed. Valid options +# include: +#	us		(MM-DD-YYYY HH:MM:SS) +#	euro    	(DD-MM-YYYY HH:MM:SS) +#	iso8601		(YYYY-MM-DD HH:MM:SS) +#	strict-iso8601	(YYYY-MM-DDTHH:MM:SS) +# + +date_format=iso8601 + + + + +# TIMEZONE OFFSET +# This option is used to override the default timezone that this +# instance of Nagios runs in.  If not specified, Nagios will use +# the system configured timezone. +# +# NOTE: In order to display the correct timezone in the CGIs, you +# will also need to alter the Apache directives for the CGI path +# to include your timezone.  Example: +# +#   <Directory "/usr/local/nagios/sbin/"> +#      SetEnv TZ "Australia/Brisbane" +#      ... +#   </Directory> + +#use_timezone=US/Mountain +#use_timezone=Australia/Brisbane + + + + +# P1.PL FILE LOCATION +# This value determines where the p1.pl perl script (used by the +# embedded Perl interpreter) is located.  If you didn't compile +# Nagios with embedded Perl support, this option has no effect. + +p1_file=/usr/lib/nagios3/p1.pl + + + +# EMBEDDED PERL INTERPRETER OPTION +# This option determines whether or not the embedded Perl interpreter +# will be enabled during runtime.  This option has no effect if Nagios +# has not been compiled with support for embedded Perl. +# Values: 0 = disable interpreter, 1 = enable interpreter + +enable_embedded_perl=1 + + + +# EMBEDDED PERL USAGE OPTION +# This option determines whether or not Nagios will process Perl plugins +# and scripts with the embedded Perl interpreter if the plugins/scripts +# do not explicitly indicate whether or not it is okay to do so. Read +# the HTML documentation on the embedded Perl interpreter for more +# information on how this option works. + +use_embedded_perl_implicitly=1 + + + +# ILLEGAL OBJECT NAME CHARACTERS +# This option allows you to specify illegal characters that cannot +# be used in host names, service descriptions, or names of other +# object types. + +illegal_object_name_chars=`~!$%^&*|'"<>?,()= + + + +# ILLEGAL MACRO OUTPUT CHARACTERS +# This option allows you to specify illegal characters that are +# stripped from macros before being used in notifications, event +# handlers, etc.  This DOES NOT affect macros used in service or +# host check commands. +# The following macros are stripped of the characters you specify: +#	$HOSTOUTPUT$ +#	$HOSTPERFDATA$ +#	$HOSTACKAUTHOR$ +#	$HOSTACKCOMMENT$ +#	$SERVICEOUTPUT$ +#	$SERVICEPERFDATA$ +#	$SERVICEACKAUTHOR$ +#	$SERVICEACKCOMMENT$ + +illegal_macro_output_chars=`~$&|'"<> + + + +# REGULAR EXPRESSION MATCHING +# This option controls whether or not regular expression matching +# takes place in the object config files.  Regular expression +# matching is used to match host, hostgroup, service, and service +# group names/descriptions in some fields of various object types. +# Values: 1 = enable regexp matching, 0 = disable regexp matching + +use_regexp_matching=0 + + + +# "TRUE" REGULAR EXPRESSION MATCHING +# This option controls whether or not "true" regular expression +# matching takes place in the object config files.  This option +# only has an effect if regular expression matching is enabled +# (see above).  If this option is DISABLED, regular expression +# matching only occurs if a string contains wildcard characters +# (* and ?).  If the option is ENABLED, regexp matching occurs +# all the time (which can be annoying). +# Values: 1 = enable true matching, 0 = disable true matching + +use_true_regexp_matching=0 + + + +# ADMINISTRATOR EMAIL/PAGER ADDRESSES +# The email and pager address of a global administrator (likely you). +# Nagios never uses these values itself, but you can access them by +# using the $ADMINEMAIL$ and $ADMINPAGER$ macros in your notification +# commands. + +admin_email=root@localhost +admin_pager=pageroot@localhost + + + +# DAEMON CORE DUMP OPTION +# This option determines whether or not Nagios is allowed to create +# a core dump when it runs as a daemon.  Note that it is generally +# considered bad form to allow this, but it may be useful for +# debugging purposes.  Enabling this option doesn't guarantee that +# a core file will be produced, but that's just life... +# Values: 1 - Allow core dumps +#         0 - Do not allow core dumps (default) + +daemon_dumps_core=0 + + + +# LARGE INSTALLATION TWEAKS OPTION +# This option determines whether or not Nagios will take some shortcuts +# which can save on memory and CPU usage in large Nagios installations. +# Read the documentation for more information on the benefits/tradeoffs +# of enabling this option. +# Values: 1 - Enabled tweaks +#         0 - Disable tweaks (default) + +use_large_installation_tweaks=0 + + + +# ENABLE ENVIRONMENT MACROS +# This option determines whether or not Nagios will make all standard +# macros available as environment variables when host/service checks +# and system commands (event handlers, notifications, etc.) are +# executed.  Enabling this option can cause performance issues in +# large installations, as it will consume a bit more memory and (more +# importantly) consume more CPU. +# Values: 1 - Enable environment variable macros (default) +#         0 - Disable environment variable macros + +enable_environment_macros=1 + + + +# CHILD PROCESS MEMORY OPTION +# This option determines whether or not Nagios will free memory in +# child processes (processed used to execute system commands and host/ +# service checks).  If you specify a value here, it will override +# program defaults. +# Value: 1 - Free memory in child processes +#        0 - Do not free memory in child processes + +#free_child_process_memory=1 + + + +# CHILD PROCESS FORKING BEHAVIOR +# This option determines how Nagios will fork child processes +# (used to execute system commands and host/service checks).  Normally +# child processes are fork()ed twice, which provides a very high level +# of isolation from problems.  Fork()ing once is probably enough and will +# save a great deal on CPU usage (in large installs), so you might +# want to consider using this.  If you specify a value here, it will +# program defaults. +# Value: 1 - Child processes fork() twice +#        0 - Child processes fork() just once + +#child_processes_fork_twice=1 + + + +# DEBUG LEVEL +# This option determines how much (if any) debugging information will +# be written to the debug file.  OR values together to log multiple +# types of information. +# Values: +#          -1 = Everything +#          0 = Nothing +#	   1 = Functions +#          2 = Configuration +#          4 = Process information +#	   8 = Scheduled events +#          16 = Host/service checks +#          32 = Notifications +#          64 = Event broker +#          128 = External commands +#          256 = Commands +#          512 = Scheduled downtime +#          1024 = Comments +#          2048 = Macros + +debug_level=0 + + + +# DEBUG VERBOSITY +# This option determines how verbose the debug log out will be. +# Values: 0 = Brief output +#         1 = More detailed +#         2 = Very detailed + +debug_verbosity=1 + + + +# DEBUG FILE +# This option determines where Nagios should write debugging information. + +debug_file=/var/lib/nagios3/nagios.debug + + + +# MAX DEBUG FILE SIZE +# This option determines the maximum size (in bytes) of the debug file.  If +# the file grows larger than this size, it will be renamed with a .old +# extension.  If a file already exists with a .old extension it will +# automatically be deleted.  This helps ensure your disk space usage doesn't +# get out of control when debugging Nagios. + +max_debug_file_size=1000000 + +process_performance_data=1 +service_perfdata_file=/var/lib/nagios3/service-perfdata +service_perfdata_file_template=DATATYPE::SERVICEPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tSERVICEDESC::$SERVICEDESC$\tSERVICEPERFDATA::$SERVICEPERFDATA$\tSERVICECHECKCOMMAND::$SERVICECHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$\tSERVICESTATE::$SERVICESTATE$\tSERVICESTATETYPE::$SERVICESTATETYPE$ +service_perfdata_file_mode=a +service_perfdata_file_processing_interval=15 +service_perfdata_file_processing_command=process-service-perfdata-file-pnp4nagios-bulk-npcd +host_perfdata_file=/var/lib/nagios3/host-perfdata +host_perfdata_file_template=DATATYPE::HOSTPERFDATA\tTIMET::$TIMET$\tHOSTNAME::$HOSTNAME$\tHOSTPERFDATA::$HOSTPERFDATA$\tHOSTCHECKCOMMAND::$HOSTCHECKCOMMAND$\tHOSTSTATE::$HOSTSTATE$\tHOSTSTATETYPE::$HOSTSTATETYPE$ +host_perfdata_file_mode=a +host_perfdata_file_processing_interval=15 +host_perfdata_file_processing_command=process-host-perfdata-file-pnp4nagios-bulk-npcd + diff --git a/puppet/modules/site_nagios/files/plugins/check_last_regex_in_log b/puppet/modules/site_nagios/files/plugins/check_last_regex_in_log new file mode 100755 index 00000000..47569388 --- /dev/null +++ b/puppet/modules/site_nagios/files/plugins/check_last_regex_in_log @@ -0,0 +1,85 @@ +#!/bin/sh +# +# depends on nagios-plugins-common for /usr/lib/nagios/plugins/utils.sh +# this package is installed using leap_platform by the Site_check_mk::Agent::Mrpe +# class + +set -e + +usage() +{ +cat << EOF +usage: $0 -w <sec> -c <sec> -r <regexp> -f <filename> + +OPTIONS: +  -h         Show this message +  -r <regex> regex to grep for +  -f <file>  logfile to search in +  -w <sec>   warning  state after X seconds +  -c <sec>   critical state after x seconds + +example: $0 -f /var/log/syslog -r 'tapicero' -w 300 -c 600 +EOF +} + + +. /usr/lib/nagios/plugins/utils.sh + + +warn=0 +crit=0 +log='' +regex='' + +set -- $(getopt hr:f:w:c: "$@") +while [ $# -gt 0 ] +do +    case "$1" in +    (-h) usage; exit 0 ;; +    (-f) log="$2"; shift;; +    (-r) regex="$2"; shift;; +    (-w) warn="$2"; shift;; +    (-c) crit="$2"; shift;; +    (--) shift; break;; +    (-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;; +    (*)  break;; +    esac +    shift +done + +[ $warn -eq 0 -o $crit -eq 0 -o -z "$regex" -o -z "$log" ] && ( usage; exit $STATE_UNKNOWN) +[ -f "$log" ] || (echo "$log doesn't exist"; exit $STATE_UNKNOWN) + +lastmsg=$(tac $log | grep -i $regex | head -1 |  sed 's/  / /g' | cut -d' ' -f 1-3) + +if [ -z "$lastmsg" ] +then +  summary="\"$regex\" in $log was not found" +  state=$STATE_CRITICAL +  state_text='CRITICAL' +  diff_sec=0 +else +  lastmsg_sec=$(date '+%s' -d "$lastmsg") +  now_sec=$(date '+%s') + +  diff_sec=$(($now_sec - $lastmsg_sec)) + +  if [ $diff_sec -lt $warn ]; then +    state=$STATE_OK +    state_text='OK' +  elif [ $diff_sec -lt $crit ]; then +    state=$STATE_WARNING +    state_text='WARNING' +  else +    state=$STATE_CRITICAL +    state_text='CRITICAL' +  fi + +  summary="Last occurrence of \"$regex\" in $log was $diff_sec sec ago" +fi + +# check_mk_agent output +# echo "$state Tapicero_Heatbeat sec=$diff_sec;$warn;$crit;0; $state_text - $summary" + +echo "${state_text}: $summary | seconds=${diff_sec};$warn;$crit;0;" +exit $state diff --git a/puppet/modules/site_nagios/manifests/add_host_services.pp b/puppet/modules/site_nagios/manifests/add_host_services.pp new file mode 100644 index 00000000..bd968e6f --- /dev/null +++ b/puppet/modules/site_nagios/manifests/add_host_services.pp @@ -0,0 +1,32 @@ +define site_nagios::add_host_services ( +  $domain_full_suffix, +  $domain_internal, +  $domain_internal_suffix, +  $ip_address, +  $services, +  $ssh_port, +  $environment, +  $openvpn_gateway_address='', +  ) { + +    $nagios_hostname = $domain_internal + +    # Add Nagios service + +    # First, we need to turn the serice array into hash, using a "hash template" +    # see https://github.com/ashak/puppet-resource-looping +    $nagios_service_hashpart = { +      'hostname'    => $nagios_hostname, +      'ip_address'  => $ip_address, +      'openvpn_gw'  => $openvpn_gateway_address, +      'environment' => $environment +    } +    $dynamic_parameters = { +      'service' => '%s' +    } +    $nagios_servicename = "${nagios_hostname}_%s" + +    $nagios_service_hash = create_resources_hash_from($nagios_servicename, $services, $nagios_service_hashpart, $dynamic_parameters) + +    create_resources ( site_nagios::add_service, $nagios_service_hash ) +} diff --git a/puppet/modules/site_nagios/manifests/add_service.pp b/puppet/modules/site_nagios/manifests/add_service.pp new file mode 100644 index 00000000..72cd038a --- /dev/null +++ b/puppet/modules/site_nagios/manifests/add_service.pp @@ -0,0 +1,32 @@ +define site_nagios::add_service ( +  $hostname, $ip_address, $service, $environment, $openvpn_gw = '') { + +  $ssh      = hiera_hash('ssh') +  $ssh_port = $ssh['port'] + +  case $service { +    'webapp': { +      nagios_service { +        "${name}_ssh": +          use                 => 'generic-service', +          check_command       => "check_ssh_port!${ssh_port}", +          service_description => 'SSH', +          host_name           => $hostname, +          contact_groups      => $environment; +        "${name}_cert": +          use                 => 'generic-service', +          check_command       => 'check_https_cert', +          service_description => 'Website Certificate', +          host_name           => $hostname, +          contact_groups      => $environment; +        "${name}_website": +          use                 => 'generic-service', +          check_command       => 'check_https', +          service_description => 'Website', +          host_name           => $hostname, +          contact_groups      => $environment; +      } +    } +    default:  {} +  } +} diff --git a/puppet/modules/site_nagios/manifests/init.pp b/puppet/modules/site_nagios/manifests/init.pp new file mode 100644 index 00000000..f91bfc26 --- /dev/null +++ b/puppet/modules/site_nagios/manifests/init.pp @@ -0,0 +1,13 @@ +# setup nagios on monitoring node +class site_nagios  { +  tag 'leap_service' + +  include site_config::default + +  Class['site_config::default'] -> Class['site_nagios'] + +  include site_nagios::server + +  # remove leftovers on monitoring nodes +  include site_config::remove::monitoring +} diff --git a/puppet/modules/site_nagios/manifests/plugins.pp b/puppet/modules/site_nagios/manifests/plugins.pp new file mode 100644 index 00000000..90a01cfb --- /dev/null +++ b/puppet/modules/site_nagios/manifests/plugins.pp @@ -0,0 +1,16 @@ +# Deploy generic plugins useful to all nodes +# nagios::plugin won't work to deploy a plugin +# because it complains with: +# Could not find dependency Package[nagios-plugins] … +# at /srv/leap/puppet/modules/nagios/manifests/plugin.pp:18 +class site_nagios::plugins { + +  file { [ +    '/usr/local/lib', '/usr/local/lib/nagios', +    '/usr/local/lib/nagios/plugins' ]: +      ensure => directory; +    '/usr/local/lib/nagios/plugins/check_last_regex_in_log': +      source => 'puppet:///modules/site_nagios/plugins/check_last_regex_in_log', +      mode   => '0755'; +  } +} diff --git a/puppet/modules/site_nagios/manifests/server.pp b/puppet/modules/site_nagios/manifests/server.pp new file mode 100644 index 00000000..6537124d --- /dev/null +++ b/puppet/modules/site_nagios/manifests/server.pp @@ -0,0 +1,97 @@ +# configures nagios on monitoring node +# lint:ignore:inherits_across_namespaces +class site_nagios::server inherits nagios::base { +# lint:endignore + +  $nagios_hiera     = hiera('nagios') +  $nagiosadmin_pw   = htpasswd_sha1($nagios_hiera['nagiosadmin_pw']) +  $nagios_hosts     = $nagios_hiera['hosts'] +  $nagios_contacts  = hiera('contacts') +  $environment      = $nagios_hiera['environments'] + +  include nagios::base +  include nagios::defaults::commands +  include nagios::defaults::templates +  include nagios::defaults::timeperiods +  include nagios::pnp4nagios +  include nagios::pnp4nagios::popup + +  class { 'nagios': +    # don't manage apache class from nagios, cause we already include +    # it in site_apache::common +    httpd              => 'absent', +    allow_external_cmd => true, +    storeconfigs       => false, +  } + +  # Delete nagios config files provided by packages +  # These don't get parsed by nagios.conf, but are +  # still irritating duplicates to the real config +  # files deployed by puppet in /etc/nagios3/ +  file { [ +    '/etc/nagios3/conf.d/contacts_nagios2.cfg', +    '/etc/nagios3/conf.d/extinfo_nagios2.cfg', +    '/etc/nagios3/conf.d/generic-host_nagios2.cfg', +    '/etc/nagios3/conf.d/generic-service_nagios2.cfg', +    '/etc/nagios3/conf.d/hostgroups_nagios2.cfg', +    '/etc/nagios3/conf.d/localhost_nagios2.cfg', +    '/etc/nagios3/conf.d/pnp4nagios.cfg', +    '/etc/nagios3/conf.d/services_nagios2.cfg', +    '/etc/nagios3/conf.d/timeperiods_nagios2.cfg' ]: +      ensure => absent; +  } + +  # deploy apache nagios3 config +  # until https://gitlab.com/shared-puppet-modules-group/apache/issues/11 +  # is not fixed, we need to manually deploy the config file +  file { +    '/etc/apache2/conf-available/nagios3.conf': +      ensure  => present, +      source  => 'puppet:///modules/nagios/configs/apache2.conf', +      require => [ Package['nagios3'], Package['apache2'] ]; +    '/etc/apache2/conf-enabled/nagios3.conf': +      ensure  => link, +      target  => '/etc/apache2/conf-available/nagios3.conf', +      require => [ Package['nagios3'], Package['apache2'] ]; +  } + +  include site_apache::common +  include site_webapp::common_vhost +  include apache::module::headers + +  File['nagios_htpasswd'] { +    source  => undef, +    content => "nagiosadmin:${nagiosadmin_pw}", +    mode    => '0640', +  } + + +  # deploy serverside plugins +  file { '/usr/lib/nagios/plugins/check_openvpn_server.pl': +    source  => 'puppet:///modules/nagios/plugins/check_openvpn_server.pl', +    mode    => '0755', +    owner   => 'nagios', +    group   => 'nagios', +    require => Package['nagios-plugins']; +  } + +  create_resources ( site_nagios::add_host_services, $nagios_hosts ) + +  include site_nagios::server::apache +  include site_check_mk::server +  include site_shorewall::monitor +  include site_nagios::server::icli + +  augeas { +    'logrotate_nagios': +      context => '/files/etc/logrotate.d/nagios/rule', +      changes => [ 'set file /var/log/nagios3/nagios.log', 'set rotate 7', +        'set schedule daily', 'set compress compress', +        'set missingok missingok', 'set ifempty notifempty', +        'set copytruncate copytruncate' ] +  } + +  create_resources ( site_nagios::server::hostgroup, $environment ) +  create_resources ( site_nagios::server::contactgroup, $environment ) +  create_resources ( site_nagios::server::add_contacts, $environment ) +} diff --git a/puppet/modules/site_nagios/manifests/server/add_contacts.pp b/puppet/modules/site_nagios/manifests/server/add_contacts.pp new file mode 100644 index 00000000..b5c6f0a5 --- /dev/null +++ b/puppet/modules/site_nagios/manifests/server/add_contacts.pp @@ -0,0 +1,18 @@ +# configure a nagios_contact +define site_nagios::server::add_contacts ($contact_emails) { + +  $environment = $name + +  nagios_contact { +    $environment: +      alias                         => $environment, +      service_notification_period   => '24x7', +      host_notification_period      => '24x7', +      service_notification_options  => 'w,u,c,r', +      host_notification_options     => 'd,r', +      service_notification_commands => 'notify-service-by-email', +      host_notification_commands    => 'notify-host-by-email', +      email                         => join($contact_emails, ', '), +      require                       => Package['nagios'] +  } +} diff --git a/puppet/modules/site_nagios/manifests/server/apache.pp b/puppet/modules/site_nagios/manifests/server/apache.pp new file mode 100644 index 00000000..82962e89 --- /dev/null +++ b/puppet/modules/site_nagios/manifests/server/apache.pp @@ -0,0 +1,25 @@ +# set up apache for nagios +class site_nagios::server::apache { + +  include x509::variables + +  include site_config::x509::commercial::cert +  include site_config::x509::commercial::key +  include site_config::x509::commercial::ca + +  include apache::module::authn_file +  # "AuthUserFile" +  include apache::module::authz_user +  # "AuthType Basic" +  include apache::module::auth_basic +  # "DirectoryIndex" +  include apache::module::dir +  include apache::module::php5 +  include apache::module::cgi + +  # apache >= 2.4, debian jessie +  if ( $::lsbdistcodename == 'jessie' ) { +    include apache::module::authn_core +  } + +} diff --git a/puppet/modules/site_nagios/manifests/server/contactgroup.pp b/puppet/modules/site_nagios/manifests/server/contactgroup.pp new file mode 100644 index 00000000..5e60dd06 --- /dev/null +++ b/puppet/modules/site_nagios/manifests/server/contactgroup.pp @@ -0,0 +1,8 @@ +# configure a contactgroup +define site_nagios::server::contactgroup ($contact_emails) { + +  nagios_contactgroup { $name: +    members => $name, +    require => Package['nagios'] +  } +} diff --git a/puppet/modules/site_nagios/manifests/server/hostgroup.pp b/puppet/modules/site_nagios/manifests/server/hostgroup.pp new file mode 100644 index 00000000..0692fced --- /dev/null +++ b/puppet/modules/site_nagios/manifests/server/hostgroup.pp @@ -0,0 +1,7 @@ +# create a nagios hostsgroup +define site_nagios::server::hostgroup ($contact_emails) { +  nagios_hostgroup { $name: +    ensure  => present, +    require => Package['nagios'] +  } +} diff --git a/puppet/modules/site_nagios/manifests/server/icli.pp b/puppet/modules/site_nagios/manifests/server/icli.pp new file mode 100644 index 00000000..26fba725 --- /dev/null +++ b/puppet/modules/site_nagios/manifests/server/icli.pp @@ -0,0 +1,26 @@ +# Install icli package and configure ncli aliases  +class site_nagios::server::icli { +  $nagios_hiera     = hiera('nagios') +  $environments     = $nagios_hiera['environments'] + +  package { 'icli': +    ensure => installed; +  } + +  file { '/root/.bashrc': +    ensure => present; +  } + +  file_line { 'icli aliases': +    path => '/root/.bashrc', +    line => 'source /root/.icli_aliases'; +  } + +  file { '/root/.icli_aliases': +    content => template("${module_name}/icli_aliases.erb"), +    mode    => '0644', +    owner   => root, +    group   => 0, +    require => Package['icli']; +  } +}
\ No newline at end of file diff --git a/puppet/modules/site_nagios/templates/icli_aliases.erb b/puppet/modules/site_nagios/templates/icli_aliases.erb new file mode 100644 index 00000000..bcb2abb0 --- /dev/null +++ b/puppet/modules/site_nagios/templates/icli_aliases.erb @@ -0,0 +1,7 @@ +alias ncli='icli -c /var/cache/nagios3/objects.cache -f /var/cache/nagios3/status.dat  -F /var/lib/nagios3/rw/nagios.cmd' +alias ncli_problems='ncli -z '!o,!A'' + +<% @environments.keys.sort.each do |env_name| %> +alias ncli_<%= env_name %>='ncli -z '!o,!A' -g <%= env_name %>' +alias ncli_<%= env_name %>_recheck='ncli -s Check_MK -g <%= env_name %> -a R' +<% end -%> diff --git a/puppet/modules/site_nickserver/manifests/init.pp b/puppet/modules/site_nickserver/manifests/init.pp new file mode 100644 index 00000000..eb4415e7 --- /dev/null +++ b/puppet/modules/site_nickserver/manifests/init.pp @@ -0,0 +1,178 @@ +# +# TODO: currently, this is dependent on some things that are set up in +# site_webapp +# +# (1) HAProxy -> couchdb +# (2) Apache +# +# It would be good in the future to make nickserver installable independently of +# site_webapp. +# + +class site_nickserver { +  tag 'leap_service' +  Class['site_config::default'] -> Class['site_nickserver'] + +  include site_config::ruby::dev + +  # +  # VARIABLES +  # + +  $nickserver        = hiera('nickserver') +  $nickserver_domain = $nickserver['domain'] +  $couchdb_user      = $nickserver['couchdb_nickserver_user']['username'] +  $couchdb_password  = $nickserver['couchdb_nickserver_user']['password'] + +  # the port that public connects to (should be 6425) +  $nickserver_port   = $nickserver['port'] +  # the port that nickserver is actually running on +  $nickserver_local_port = '64250' + +  # couchdb is available on localhost via haproxy, which is bound to 4096. +  $couchdb_host      = 'localhost' +  # See site_webapp/templates/haproxy_couchdb.cfg.erg +  $couchdb_port      = '4096' + +  $sources           = hiera('sources') + +  # temporarily for now: +  $domain          = hiera('domain') +  $address_domain  = $domain['full_suffix'] + +  include site_config::x509::cert +  include site_config::x509::key +  include site_config::x509::ca + +  # +  # USER AND GROUP +  # + +  group { 'nickserver': +    ensure    => present, +    allowdupe => false; +  } + +  user { 'nickserver': +    ensure    => present, +    allowdupe => false, +    gid       => 'nickserver', +    home      => '/srv/leap/nickserver', +    require   => Group['nickserver']; +  } + +  vcsrepo { '/srv/leap/nickserver': +    ensure   => present, +    revision => $sources['nickserver']['revision'], +    provider => $sources['nickserver']['type'], +    source   => $sources['nickserver']['source'], +    owner    => 'nickserver', +    group    => 'nickserver', +    require  => [ User['nickserver'], Group['nickserver'] ], +    notify   => Exec['nickserver_bundler_update']; +  } + +  exec { 'nickserver_bundler_update': +    cwd     => '/srv/leap/nickserver', +    command => '/bin/bash -c "/usr/bin/bundle check || /usr/bin/bundle install --path vendor/bundle"', +    unless  => '/usr/bin/bundle check', +    user    => 'nickserver', +    timeout => 600, +    require => [ +      Class['bundler::install'], Vcsrepo['/srv/leap/nickserver'], +      Package['libssl-dev'], Class['site_config::ruby::dev'] ], + +    notify  => Service['nickserver']; +  } + +  # +  # NICKSERVER CONFIG +  # + +  file { '/etc/nickserver.yml': +    content => template('site_nickserver/nickserver.yml.erb'), +    owner   => nickserver, +    group   => nickserver, +    mode    => '0600', +    notify  => Service['nickserver']; +  } + +  # +  # NICKSERVER DAEMON +  # + +  file { +    '/usr/bin/nickserver': +      ensure  => link, +      target  => '/srv/leap/nickserver/bin/nickserver', +      require => Vcsrepo['/srv/leap/nickserver']; + +    '/etc/init.d/nickserver': +      owner   => root, +      group   => 0, +      mode    => '0755', +      source  => '/srv/leap/nickserver/dist/debian-init-script', +      require => Vcsrepo['/srv/leap/nickserver']; +  } + +  # register initscript at systemd on nodes newer than wheezy +  # see https://leap.se/code/issues/7614 +  case $::operatingsystemrelease { +    /^7.*/: { } +    default:  { +      exec { 'register_systemd_nickserver': +        refreshonly => true, +        command     => '/bin/systemctl enable nickserver', +        subscribe   => File['/etc/init.d/nickserver'], +        before      => Service['nickserver']; +      } +    } +  } + +  service { 'nickserver': +    ensure     => running, +    enable     => true, +    hasrestart => true, +    hasstatus  => true, +    require    => [ +      File['/etc/init.d/nickserver'], +      File['/usr/bin/nickserver'], +      Class['Site_config::X509::Key'], +      Class['Site_config::X509::Cert'], +      Class['Site_config::X509::Ca'] ]; +  } + +  # +  # FIREWALL +  # poke a hole in the firewall to allow nickserver requests +  # + +  file { '/etc/shorewall/macro.nickserver': +    content => "PARAM   -       -       tcp    ${nickserver_port}", +    notify  => Service['shorewall'], +    require => Package['shorewall']; +  } + +  shorewall::rule { 'net2fw-nickserver': +    source      => 'net', +    destination => '$FW', +    action      => 'nickserver(ACCEPT)', +    order       => 200; +  } + +  # +  # APACHE REVERSE PROXY +  # nickserver doesn't speak TLS natively, let Apache handle that. +  # + +  apache::module { +    'proxy': ensure => present; +    'proxy_http': ensure => present +  } + +  apache::vhost::file { +    'nickserver': +      content => template('site_nickserver/nickserver-proxy.conf.erb') +  } + +} diff --git a/puppet/modules/site_nickserver/templates/nickserver-proxy.conf.erb b/puppet/modules/site_nickserver/templates/nickserver-proxy.conf.erb new file mode 100644 index 00000000..8f59fe38 --- /dev/null +++ b/puppet/modules/site_nickserver/templates/nickserver-proxy.conf.erb @@ -0,0 +1,19 @@ +# +# Apache reverse proxy configuration for the Nickserver +# + +Listen 0.0.0.0:<%= @nickserver_port -%> + +<VirtualHost *:<%= @nickserver_port -%>> +  ServerName <%= @nickserver_domain %> +  ServerAlias <%= @address_domain %> + +  SSLCACertificatePath /etc/ssl/certs +  SSLCertificateKeyFile <%= scope.lookupvar('x509::variables::keys') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.key +  SSLCertificateFile <%= scope.lookupvar('x509::variables::certs') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.crt + +  Include include.d/ssl_common.inc +   +  ProxyPass / http://localhost:<%= @nickserver_local_port %>/ +  ProxyPreserveHost On  # preserve Host header in HTTP request +</VirtualHost> diff --git a/puppet/modules/site_nickserver/templates/nickserver.yml.erb b/puppet/modules/site_nickserver/templates/nickserver.yml.erb new file mode 100644 index 00000000..e717cbaa --- /dev/null +++ b/puppet/modules/site_nickserver/templates/nickserver.yml.erb @@ -0,0 +1,19 @@ +# +# configuration for nickserver. +# + +domain: "<%= @address_domain %>" + +couch_host: "<%= @couchdb_host %>" +couch_port: <%= @couchdb_port %> +couch_database: "identities" +couch_user: "<%= @couchdb_user %>" +couch_password: "<%= @couchdb_password %>" + +hkp_url: "https://hkps.pool.sks-keyservers.net:/pks/lookup" + +user: "nickserver" +port: <%= @nickserver_local_port %> +pid_file: "/var/run/nickserver" +log_file: "/var/log/nickserver.log" + diff --git a/puppet/modules/site_obfsproxy/README b/puppet/modules/site_obfsproxy/README new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/puppet/modules/site_obfsproxy/README diff --git a/puppet/modules/site_obfsproxy/manifests/init.pp b/puppet/modules/site_obfsproxy/manifests/init.pp new file mode 100644 index 00000000..2ed5ec9e --- /dev/null +++ b/puppet/modules/site_obfsproxy/manifests/init.pp @@ -0,0 +1,38 @@ +class site_obfsproxy { +  tag 'leap_service' +  Class['site_config::default'] -> Class['site_obfsproxy'] + +  $transport = 'scramblesuit' + +  $obfsproxy    = hiera('obfsproxy') +  $scramblesuit = $obfsproxy['scramblesuit'] +  $scram_pass   = $scramblesuit['password'] +  $scram_port   = $scramblesuit['port'] +  $dest_ip      = $obfsproxy['gateway_address'] +  $dest_port    = '443' + +  if member($::services, 'openvpn') { +    $openvpn      = hiera('openvpn') +    $bind_address = $openvpn['gateway_address'] +  } +  elsif member($::services, 'obfsproxy') { +    $bind_address = hiera('ip_address') +  } + +  include site_config::default + +  class { 'obfsproxy': +    transport    => $transport, +    bind_address => $bind_address, +    port         => $scram_port, +    param        => $scram_pass, +    dest_ip      => $dest_ip, +    dest_port    => $dest_port, +  } + +  include site_shorewall::obfsproxy + +} + + + diff --git a/puppet/modules/site_openvpn/README b/puppet/modules/site_openvpn/README new file mode 100644 index 00000000..cef5be23 --- /dev/null +++ b/puppet/modules/site_openvpn/README @@ -0,0 +1,20 @@ +Place to look when debugging problems +======================================== + +Log files: + +    openvpn: /var/log/syslog +    shorewall: /var/log/syslog +    shorewall startup: /var/log/shorewall-init.log + +Check NAT masq: + +    iptables -t nat --list-rules + +Check interfaces: + +   ip addr ls + +Scripts: + +   /usr/local/bin/add_gateway_ips.sh
\ No newline at end of file diff --git a/puppet/modules/site_openvpn/manifests/dh_key.pp b/puppet/modules/site_openvpn/manifests/dh_key.pp new file mode 100644 index 00000000..13cc0f5b --- /dev/null +++ b/puppet/modules/site_openvpn/manifests/dh_key.pp @@ -0,0 +1,10 @@ +class site_openvpn::dh_key { + +  $x509_config      = hiera('x509') + +  file { '/etc/openvpn/keys/dh.pem': +    content => $x509_config['dh'], +    mode    => '0644', +  } + +} diff --git a/puppet/modules/site_openvpn/manifests/init.pp b/puppet/modules/site_openvpn/manifests/init.pp new file mode 100644 index 00000000..f1ecefb9 --- /dev/null +++ b/puppet/modules/site_openvpn/manifests/init.pp @@ -0,0 +1,238 @@ +# +# An openvpn gateway can support three modes: +# +#   (1) limited and unlimited +#   (2) unlimited only +#   (3) limited only +# +# The difference is that 'unlimited' gateways only allow client certs that match +# the 'unlimited_prefix', and 'limited' gateways only allow certs that match the +# 'limited_prefix'. +# +# We potentially create four openvpn config files (thus four daemons): +# +#   (1) unlimited + tcp => tcp_config.conf +#   (2) unlimited + udp => udp_config.conf +#   (3) limited + tcp => limited_tcp_config.conf +#   (4) limited + udp => limited_udp_config.conf +# + +class site_openvpn { +  tag 'leap_service' + +  include site_config::x509::cert +  include site_config::x509::key +  include site_config::x509::ca_bundle + +  include site_config::default +  Class['site_config::default'] -> Class['site_openvpn'] + +  include ::site_obfsproxy + +  $openvpn          = hiera('openvpn') +  $openvpn_ports    = $openvpn['ports'] +  $openvpn_config   = $openvpn['configuration'] + +  if $::ec2_instance_id { +    $openvpn_gateway_address = $::ipaddress +  } else { +    $openvpn_gateway_address         = $openvpn['gateway_address'] +    if $openvpn['second_gateway_address'] { +      $openvpn_second_gateway_address = $openvpn['second_gateway_address'] +    } else { +      $openvpn_second_gateway_address = undef +    } +  } + +  $openvpn_allow_unlimited              = $openvpn['allow_unlimited'] +  $openvpn_unlimited_prefix             = $openvpn['unlimited_prefix'] +  $openvpn_unlimited_tcp_network_prefix = '10.41.0' +  $openvpn_unlimited_tcp_netmask        = '255.255.248.0' +  $openvpn_unlimited_tcp_cidr           = '21' +  $openvpn_unlimited_udp_network_prefix = '10.42.0' +  $openvpn_unlimited_udp_netmask        = '255.255.248.0' +  $openvpn_unlimited_udp_cidr           = '21' + +  if !$::ec2_instance_id { +    $openvpn_allow_limited                = $openvpn['allow_limited'] +    $openvpn_limited_prefix               = $openvpn['limited_prefix'] +    $openvpn_rate_limit                   = $openvpn['rate_limit'] +    $openvpn_limited_tcp_network_prefix   = '10.43.0' +    $openvpn_limited_tcp_netmask          = '255.255.248.0' +    $openvpn_limited_tcp_cidr             = '21' +    $openvpn_limited_udp_network_prefix   = '10.44.0' +    $openvpn_limited_udp_netmask          = '255.255.248.0' +    $openvpn_limited_udp_cidr             = '21' +  } + +  # find out the netmask in cidr format of the primary IF +  # thx to https://blog.kumina.nl/tag/puppet-tips-and-tricks/ +  # we can do this using an inline_template: +  $factname_primary_netmask = "netmask_cidr_${::site_config::params::interface}" +  $primary_netmask = inline_template('<%= scope.lookupvar(@factname_primary_netmask) %>') + +  # deploy dh keys +  include site_openvpn::dh_key + +  if $openvpn_allow_unlimited and $openvpn_allow_limited { +    $unlimited_gateway_address = $openvpn_gateway_address +    $limited_gateway_address = $openvpn_second_gateway_address +  } elsif $openvpn_allow_unlimited { +    $unlimited_gateway_address = $openvpn_gateway_address +    $limited_gateway_address = undef +  } elsif $openvpn_allow_limited { +    $unlimited_gateway_address = undef +    $limited_gateway_address = $openvpn_gateway_address +  } + +  if $openvpn_allow_unlimited { +    site_openvpn::server_config { 'tcp_config': +      port       => '1194', +      proto      => 'tcp', +      local      => $unlimited_gateway_address, +      tls_remote => "\"${openvpn_unlimited_prefix}\"", +      server     => "${openvpn_unlimited_tcp_network_prefix}.0 ${openvpn_unlimited_tcp_netmask}", +      push       => "\"dhcp-option DNS ${openvpn_unlimited_tcp_network_prefix}.1\"", +      management => '127.0.0.1 1000', +      config     => $openvpn_config +    } +    site_openvpn::server_config { 'udp_config': +      port       => '1194', +      proto      => 'udp', +      local      => $unlimited_gateway_address, +      tls_remote => "\"${openvpn_unlimited_prefix}\"", +      server     => "${openvpn_unlimited_udp_network_prefix}.0 ${openvpn_unlimited_udp_netmask}", +      push       => "\"dhcp-option DNS ${openvpn_unlimited_udp_network_prefix}.1\"", +      management => '127.0.0.1 1001', +      config     => $openvpn_config +    } +  } else { +    tidy { '/etc/openvpn/tcp_config.conf': } +    tidy { '/etc/openvpn/udp_config.conf': } +  } + +  if $openvpn_allow_limited { +    site_openvpn::server_config { 'limited_tcp_config': +      port       => '1194', +      proto      => 'tcp', +      local      => $limited_gateway_address, +      tls_remote => "\"${openvpn_limited_prefix}\"", +      server     => "${openvpn_limited_tcp_network_prefix}.0 ${openvpn_limited_tcp_netmask}", +      push       => "\"dhcp-option DNS ${openvpn_limited_tcp_network_prefix}.1\"", +      management => '127.0.0.1 1002', +      config     => $openvpn_config +    } +    site_openvpn::server_config { 'limited_udp_config': +      port       => '1194', +      proto      => 'udp', +      local      => $limited_gateway_address, +      tls_remote => "\"${openvpn_limited_prefix}\"", +      server     => "${openvpn_limited_udp_network_prefix}.0 ${openvpn_limited_udp_netmask}", +      push       => "\"dhcp-option DNS ${openvpn_limited_udp_network_prefix}.1\"", +      management => '127.0.0.1 1003', +      config     => $openvpn_config +    } +  } else { +    tidy { '/etc/openvpn/limited_tcp_config.conf': } +    tidy { '/etc/openvpn/limited_udp_config.conf': } +  } + +  file { +    '/usr/local/bin/add_gateway_ips.sh': +      content => template('site_openvpn/add_gateway_ips.sh.erb'), +      mode    => '0755'; +  } + +  exec { '/usr/local/bin/add_gateway_ips.sh': +    subscribe   => File['/usr/local/bin/add_gateway_ips.sh'], +  } + +  exec { 'restart_openvpn': +    command     => '/etc/init.d/openvpn restart', +    refreshonly => true, +    subscribe   => [ +                    File['/etc/openvpn'], +                    Class['Site_config::X509::Key'], +                    Class['Site_config::X509::Cert'], +                    Class['Site_config::X509::Ca_bundle'] ], +    require     => [ +                    Package['openvpn'], +                    File['/etc/openvpn'], +                    Class['Site_config::X509::Key'], +                    Class['Site_config::X509::Cert'], +                    Class['Site_config::X509::Ca_bundle'] ]; +  } + +  cron { 'add_gateway_ips.sh': +    command => '/usr/local/bin/add_gateway_ips.sh', +    user    => 'root', +    special => 'reboot', +  } + +  # setup the resolver to listen on the vpn IP +  include site_openvpn::resolver + +  include site_shorewall::eip + +  package { +    'openvpn': ensure => latest +  } + +  service { +    'openvpn': +      ensure     => running, +      hasrestart => true, +      hasstatus  => true, +      require    => [ +        Package['openvpn'], +        Exec['concat_/etc/default/openvpn'] ]; +  } + +  file { +    '/etc/openvpn': +      ensure  => directory, +      notify  => Exec['restart_openvpn'], +      require => Package['openvpn']; +  } + +  file { +    '/etc/openvpn/keys': +      ensure  => directory, +      require => Package['openvpn']; +  } + +  concat { +    '/etc/default/openvpn': +      owner  => root, +      group  => root, +      mode   => 644, +      warn   => true, +      notify => Service['openvpn']; +  } + +  concat::fragment { +    'openvpn.default.header': +      content => template('openvpn/etc-default-openvpn.erb'), +      target  => '/etc/default/openvpn', +      order   => 01; +  } + +  concat::fragment { +    "openvpn.default.autostart.${name}": +      content => 'AUTOSTART=all', +      target  => '/etc/default/openvpn', +      order   => 10; +  } + +  leap::logfile { 'openvpn_tcp': } +  leap::logfile { 'openvpn_udp': } + +  # Because we currently do not support ipv6 and instead block it (so no leaks +  # happen), we get a large number of these messages, so we ignore them (#6540) +  rsyslog::snippet { '01-ignore_icmpv6_send': +    content => ':msg, contains, "icmpv6_send: no reply to icmp error" ~' +  } + +  include site_check_mk::agent::openvpn + +} diff --git a/puppet/modules/site_openvpn/manifests/resolver.pp b/puppet/modules/site_openvpn/manifests/resolver.pp new file mode 100644 index 00000000..cea0153a --- /dev/null +++ b/puppet/modules/site_openvpn/manifests/resolver.pp @@ -0,0 +1,50 @@ +class site_openvpn::resolver { + +  if $site_openvpn::openvpn_allow_unlimited { +    $ensure_unlimited = 'present' +    file { +      '/etc/unbound/unbound.conf.d/vpn_unlimited_udp_resolver.conf': +        content => "server:\n\tinterface: ${site_openvpn::openvpn_unlimited_udp_network_prefix}.1\n\taccess-control: ${site_openvpn::openvpn_unlimited_udp_network_prefix}.0/${site_openvpn::openvpn_unlimited_udp_cidr} allow\n", +        owner   => root, +        group   => root, +        mode    => '0644', +        require => [ Class['site_config::caching_resolver'], Service['openvpn'] ], +        notify  => Service['unbound']; +      '/etc/unbound/unbound.conf.d/vpn_unlimited_tcp_resolver.conf': +        content => "server:\n\tinterface: ${site_openvpn::openvpn_unlimited_tcp_network_prefix}.1\n\taccess-control: ${site_openvpn::openvpn_unlimited_tcp_network_prefix}.0/${site_openvpn::openvpn_unlimited_tcp_cidr} allow\n", +        owner   => root, +        group   => root, +        mode    => '0644', +        require => [ Class['site_config::caching_resolver'], Service['openvpn'] ], +        notify  => Service['unbound']; +    } +  } else { +    $ensure_unlimited = 'absent' +    tidy { '/etc/unbound/unbound.conf.d/vpn_unlimited_udp_resolver.conf': } +    tidy { '/etc/unbound/unbound.conf.d/vpn_unlimited_tcp_resolver.conf': } +  } + +  if $site_openvpn::openvpn_allow_limited { +    $ensure_limited = 'present' +    file { +      '/etc/unbound/unbound.conf.d/vpn_limited_udp_resolver.conf': +        content => "server:\n\tinterface: ${site_openvpn::openvpn_limited_udp_network_prefix}.1\n\taccess-control: ${site_openvpn::openvpn_limited_udp_network_prefix}.0/${site_openvpn::openvpn_limited_udp_cidr} allow\n", +        owner   => root, +        group   => root, +        mode    => '0644', +        require => [ Class['site_config::caching_resolver'], Service['openvpn'] ], +        notify  => Service['unbound']; +      '/etc/unbound/unbound.conf.d/vpn_limited_tcp_resolver.conf': +        content => "server\n\tinterface: ${site_openvpn::openvpn_limited_tcp_network_prefix}.1\n\taccess-control: ${site_openvpn::openvpn_limited_tcp_network_prefix}.0/${site_openvpn::openvpn_limited_tcp_cidr} allow\n", +        owner   => root, +        group   => root, +        mode    => '0644', +        require => [ Class['site_config::caching_resolver'], Service['openvpn'] ], +        notify  => Service['unbound']; +    } +  } else { +    $ensure_limited = 'absent' +    tidy { '/etc/unbound/unbound.conf.d/vpn_limited_udp_resolver.conf': } +    tidy { '/etc/unbound/unbound.conf.d/vpn_limited_tcp_resolver.conf': } +  } +} diff --git a/puppet/modules/site_openvpn/manifests/server_config.pp b/puppet/modules/site_openvpn/manifests/server_config.pp new file mode 100644 index 00000000..15e6fb38 --- /dev/null +++ b/puppet/modules/site_openvpn/manifests/server_config.pp @@ -0,0 +1,228 @@ +# +# Cipher discussion +# ================================ +# +# We want to specify explicit values for the crypto options to prevent a MiTM from forcing +# a weaker cipher. These should be set in both the server and the client ('auth' and 'cipher' +# MUST be the same on both ends or no data will get transmitted). +# +# tls-cipher DHE-RSA-AES128-SHA +# +#   dkg: For the TLS control channel, we want to make sure we choose a +#   key exchange mechanism that has PFS (meaning probably some form of ephemeral +#   Diffie-Hellman key exchange), and that uses a standard, well-tested cipher +#   (I recommend AES, and 128 bits is probably fine, since there are some known +#   weaknesses in the 192- and 256-bit key schedules). That leaves us with the +#   choice of public key algorithms: /usr/sbin/openvpn --show-tls | grep DHE | +#   grep AES128 | grep GCM. +# +#   elijah: +#   I could not get any of these working: +#     * openvpn --show-tls | grep GCM +#     * openvpn --show-tls | grep DHE | grep AES128 | grep SHA256 +#   so, i went with this: +#     * openvpn --show-tls | grep DHE | grep AES128 | grep -v SHA256 | grep -v GCM +#   Also, i couldn't get any of the elliptical curve algorithms to work. Not sure how +#   our cert generation interacts with the tls-cipher algorithms. +# +#   note: in my tests, DHE-RSA-AES256-SHA is the one it negotiates if no value is set. +# +# auth SHA1 +# +#   dkg: For HMAC digest to authenticate packets, we just want SHA256. OpenVPN lists +#   a number of "digest" with names like "RSA-SHA256", but this are legacy and +#   should be avoided. +# +#   elijah: i am not so sure that the digest algo matters for 'auth' option, because +#   i think an attacker would have to forge the digest in real time, which is still far from +#   a possibility for SHA1. So, i am leaving the default for now (SHA1). +# +# cipher AES-128-CBC +# +#   dkg: For the choice of cipher, we need to select an algorithm and a +#   cipher mode. OpenVPN defaults to Blowfish, which is a fine algorithm - but +#   our control channel is already relying on AES not being broken; if the +#   control channel is cracked, then the key material for the tunnel is exposed, +#   and the choice of algorithm is moot. So it makes more sense to me to rely on +#   the same cipher here: AES128. As for the cipher mode, OFB seems cleaner to +#   me, but CBC is more well-tested, and the OpenVPN man page (at least as of +#   version 2.2.1) says "CBC is recommended and CFB and OFB should be considered +#   advanced modes." +# +#   note: the default is BF-CBC (blowfish) +# + +define site_openvpn::server_config( +  $port, $proto, $local, $server, $push, +  $management, $config, $tls_remote = undef) { + +  $openvpn_configname = $name +  $shortname = regsubst(regsubst($name, '_config', ''), '_', '-') +  $openvpn_status_filename = "/var/run/openvpn-status-${shortname}" + +  concat { +    "/etc/openvpn/${openvpn_configname}.conf": +      owner   => root, +      group   => root, +      mode    => 644, +      warn    => true, +      require => File['/etc/openvpn'], +      before  => Service['openvpn'], +      notify  => Exec['restart_openvpn']; +  } + +  if $tls_remote != undef { +    openvpn::option { +      "tls-remote ${openvpn_configname}": +        key     => 'tls-remote', +        value   => $tls_remote, +        server  => $openvpn_configname; +    } +  } + +  # according to openvpn man page: tcp-nodelay is a "generally a good latency optimization". +  if $proto == 'tcp' { +    openvpn::option { +      "tcp-nodelay ${openvpn_configname}": +        key     => 'tcp-nodelay', +        server  => $openvpn_configname; +    } +  } elsif $proto == 'udp' { +    if $config['fragment'] != 1500 { +      openvpn::option { +        "fragment ${openvpn_configname}": +          key    => 'fragment', +          value  => $config['fragment'], +          server => $openvpn_configname; +        "mssfix ${openvpn_configname}": +          key    => 'mssfix', +          server => $openvpn_configname; +      } +    } +  } + +  openvpn::option { +    "ca ${openvpn_configname}": +      key     => 'ca', +      value   => "${x509::variables::local_CAs}/${site_config::params::ca_bundle_name}.crt", +      server  => $openvpn_configname; +    "cert ${openvpn_configname}": +      key     => 'cert', +      value   => "${x509::variables::certs}/${site_config::params::cert_name}.crt", +      server  => $openvpn_configname; +    "key ${openvpn_configname}": +      key     => 'key', +      value   => "${x509::variables::keys}/${site_config::params::cert_name}.key", +      server  => $openvpn_configname; +    "dh ${openvpn_configname}": +      key     => 'dh', +      value   => '/etc/openvpn/keys/dh.pem', +      server  => $openvpn_configname; +    "tls-cipher ${openvpn_configname}": +      key     => 'tls-cipher', +      value   => $config['tls-cipher'], +      server  => $openvpn_configname; +    "auth ${openvpn_configname}": +      key     => 'auth', +      value   => $config['auth'], +      server  => $openvpn_configname; +    "cipher ${openvpn_configname}": +      key     => 'cipher', +      value   => $config['cipher'], +      server  => $openvpn_configname; +    "dev ${openvpn_configname}": +      key    => 'dev', +      value  => 'tun', +      server => $openvpn_configname; +    "tun-ipv6 ${openvpn_configname}": +      key    => 'tun-ipv6', +      server => $openvpn_configname; +    "duplicate-cn ${openvpn_configname}": +      key    => 'duplicate-cn', +      server => $openvpn_configname; +    "keepalive ${openvpn_configname}": +      key    => 'keepalive', +      value  => $config['keepalive'], +      server => $openvpn_configname; +    "local ${openvpn_configname}": +      key    => 'local', +      value  => $local, +      server => $openvpn_configname; +    "mute ${openvpn_configname}": +      key    => 'mute', +      value  => '5', +      server => $openvpn_configname; +    "mute-replay-warnings ${openvpn_configname}": +      key    => 'mute-replay-warnings', +      server => $openvpn_configname; +    "management ${openvpn_configname}": +      key    => 'management', +      value  => $management, +      server => $openvpn_configname; +    "proto ${openvpn_configname}": +      key    => 'proto', +      value  => $proto, +      server => $openvpn_configname; +    "push1 ${openvpn_configname}": +      key    => 'push', +      value  => $push, +      server => $openvpn_configname; +    "push2 ${openvpn_configname}": +      key    => 'push', +      value  => '"redirect-gateway def1"', +      server => $openvpn_configname; +    "push-ipv6 ${openvpn_configname}": +      key    => 'push', +      value  => '"route-ipv6 2000::/3"', +      server => $openvpn_configname; +    "script-security ${openvpn_configname}": +      key    => 'script-security', +      value  => '1', +      server => $openvpn_configname; +    "server ${openvpn_configname}": +      key    => 'server', +      value  => $server, +      server => $openvpn_configname; +    "server-ipv6 ${openvpn_configname}": +      key    => 'server-ipv6', +      value  => '2001:db8:123::/64', +      server => $openvpn_configname; +    "status ${openvpn_configname}": +      key    => 'status', +      value  => "${openvpn_status_filename} 10", +      server => $openvpn_configname; +    "status-version ${openvpn_configname}": +      key    => 'status-version', +      value  => '3', +      server => $openvpn_configname; +    "topology ${openvpn_configname}": +      key    => 'topology', +      value  => 'subnet', +      server => $openvpn_configname; +    "verb ${openvpn_configname}": +      key    => 'verb', +      value  => '3', +      server => $openvpn_configname; +    "log-append /var/log/leap/openvpn_${proto}.log": +      key    => 'log-append', +      value  => "/var/log/leap/openvpn_${proto}.log", +      server => $openvpn_configname; +  } + +  # register openvpn services at systemd on nodes newer than wheezy +  # see https://leap.se/code/issues/7798 +  case $::operatingsystemrelease { +    /^7.*/: { } +    default:  { +      exec { "enable_systemd_${openvpn_configname}": +        refreshonly => true, +        command     => "/bin/systemctl enable openvpn@${openvpn_configname}", +        subscribe   => File["/etc/openvpn/${openvpn_configname}.conf"], +        notify      => Service["openvpn@${openvpn_configname}"]; +      } +      service { "openvpn@${openvpn_configname}": +        ensure  => running +      } +    } +  } +} diff --git a/puppet/modules/site_openvpn/templates/add_gateway_ips.sh.erb b/puppet/modules/site_openvpn/templates/add_gateway_ips.sh.erb new file mode 100644 index 00000000..e76b756b --- /dev/null +++ b/puppet/modules/site_openvpn/templates/add_gateway_ips.sh.erb @@ -0,0 +1,11 @@ +#!/bin/sh + +ip addr show dev <%= scope.lookupvar('site_config::params::interface') %> | grep -q <%= @openvpn_gateway_address %>/<%= @primary_netmask %> || +  ip addr add <%= @openvpn_gateway_address %>/<%= @primary_netmask %> dev <%= scope.lookupvar('site_config::params::interface') %> + +<% if @openvpn_second_gateway_address %> +ip addr show dev <%= scope.lookupvar('site_config::params::interface') %> | grep -q <%= @openvpn_second_gateway_address %>/<%= @primary_netmask %> || +  ip addr add <%= @openvpn_second_gateway_address %>/<%= @primary_netmask %> dev <%= scope.lookupvar('site_config::params::interface') %> +<% end %> + +/bin/echo 1 > /proc/sys/net/ipv4/ip_forward diff --git a/puppet/modules/site_postfix/files/checks/received_anon b/puppet/modules/site_postfix/files/checks/received_anon new file mode 100644 index 00000000..9de25e63 --- /dev/null +++ b/puppet/modules/site_postfix/files/checks/received_anon @@ -0,0 +1,2 @@ +/^Received: from (.* \([-._[:alnum:]]+ \[[.[:digit:]]{7,15}\]\))([[:space:]]+).*(\(using [.[:alnum:]]+ with cipher [-A-Z0-9]+ \([0-9]+\/[0-9]+ bits\)\))[[:space:]]+\(Client CN "([-._@[:alnum:]]+)", Issuer "[[:print:]]+" \(verified OK\)\)[[:space:]]+by ([.[:alnum:]]+) \(([^)]+)\) with (E?SMTPS?A?) id ([A-F[:digit:]]+).*/ + REPLACE Received: from [127.0.0.1] (localhost [127.0.0.1])${2}${3}${2}(Authenticated sender: $4)${2}with $7 id $8 diff --git a/puppet/modules/site_postfix/manifests/debug.pp b/puppet/modules/site_postfix/manifests/debug.pp new file mode 100644 index 00000000..f370d166 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/debug.pp @@ -0,0 +1,9 @@ +class site_postfix::debug { + +  postfix::config { +    'debug_peer_list':      value => '127.0.0.1'; +    'debug_peer_level':     value => '1'; +    'smtpd_tls_loglevel':   value => '1'; +  } + +} diff --git a/puppet/modules/site_postfix/manifests/mx.pp b/puppet/modules/site_postfix/manifests/mx.pp new file mode 100644 index 00000000..c269946b --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx.pp @@ -0,0 +1,152 @@ +# +# configure mx node +# +class site_postfix::mx { + +  $domain_hash         = hiera('domain') +  $domain              = $domain_hash['full_suffix'] +  $host_domain         = $domain_hash['full'] +  $cert_name           = hiera('name') +  $mynetworks          = join(hiera('mynetworks', ''), ' ') +  $rbls                = suffix(prefix(hiera('rbls', []), 'reject_rbl_client '), ',') + +  $root_mail_recipient    = hiera('contacts') +  $postfix_smtp_listen    = 'all' +  $postfix_use_postscreen = 'yes' + +  include site_config::x509::cert +  include site_config::x509::key +  include site_config::x509::client_ca::ca +  include site_config::x509::client_ca::key + +  postfix::config { +    'mynetworks': +      value => "127.0.0.0/8 [::1]/128 [fe80::]/64 ${mynetworks}"; +    # Note: mydestination should not include @domain, because this is +    # used in virtual alias maps. +    'mydestination': +      value => "\$myorigin, localhost, localhost.\$mydomain"; +    'myhostname': +      value => $host_domain; +    'mailbox_size_limit': +      value => '0'; +    'home_mailbox': +      value => ''; +    'virtual_mailbox_domains': +      value => 'deliver.local'; +    'virtual_mailbox_base': +      value => '/var/mail/leap-mx'; +    'virtual_mailbox_maps': +      value => 'static:Maildir/'; +    # Note: virtual-aliases map will take precedence over leap-mx +    # lookup (tcp:localhost) +    'virtual_alias_maps': +      value => 'hash:/etc/postfix/virtual-aliases tcp:localhost:4242'; +    'luser_relay': +      value => ''; +    # uid and gid are set to an arbitrary hard-coded value here, this +    # must match the 'leap-mx' user/group +    'virtual_uid_maps': +      value => 'static:42424'; +    'virtual_gid_maps': +      value => 'static:42424'; +    # the two following configs are needed for matching user's client cert +    # fingerprints to enable relaying (#3634). Satellites do not have +    # these configured. +    'smtpd_tls_fingerprint_digest': +      value => 'sha1'; +    'relay_clientcerts': +      value => 'tcp:localhost:2424'; +    # Note: we are setting this here, instead of in site_postfix::mx::smtp_tls +    # because the satellites need to have a different value +    'smtp_tls_security_level': +      value => 'may'; +    # reject inbound mail to system users +    # see https://leap.se/code/issues/6829 +    # this blocks *only* mails to system users, that don't appear in the +    # alias map +    'local_recipient_maps': +      value => '$alias_maps'; +    # setup clamav and opendkim on smtpd +    'smtpd_milters': +      value => 'unix:/run/clamav/milter.ctl,inet:localhost:8891'; +    # setup opendkim for smtp (non-smtpd) outgoing mail +    'non_smtpd_milters': +      value => 'inet:localhost:8891'; +    'milter_default_action': +      value => 'accept'; +    # Make sure that the right values are set, these could be set to different +    # things on install, depending on preseed or debconf options +    # selected (see #7478) +    'relay_transport': +      value => 'relay'; +    'default_transport': +      value => 'smtp'; +    'mailbox_command': +      value => ''; +    'header_checks': +      value => ''; +    'postscreen_access_list': +      value => 'permit_mynetworks'; +    'postscreen_greet_action': +      value => 'enforce'; +  } + +  # Make sure that the cleanup serivce is not chrooted, otherwise it cannot +  # access the opendkim milter socket (#8020) +  exec { 'unset_cleanup_chroot': +    command => '/usr/sbin/postconf -F "cleanup/unix/chroot=n"', +    onlyif  => '/usr/sbin/postconf -h -F "cleanup/unix/chroot" | egrep -q ^n', +    notify  => Service['postfix'], +    require => File['/etc/postfix/master.cf'] +  } + +  include ::site_postfix::mx::smtpd_checks +  include ::site_postfix::mx::checks +  include ::site_postfix::mx::smtp_tls +  include ::site_postfix::mx::smtpd_tls +  include ::site_postfix::mx::static_aliases +  include ::site_postfix::mx::rewrite_openpgp_header +  include ::site_postfix::mx::received_anon +  include ::clamav +  include ::opendkim +  include ::postfwd + +  # greater verbosity for debugging, take out for production +  #include site_postfix::debug + +  case $::operatingsystemrelease { +    /^7.*/: { +      $smtpd_relay_restrictions='' +    } +    default:  { +      $smtpd_relay_restrictions="  -o smtpd_relay_restrictions=\$smtps_relay_restrictions\n" +    } +  } + +  $mastercf_tail = " +smtps     inet  n       -       -       -       -       smtpd +  -o smtpd_tls_wrappermode=yes +  -o smtpd_tls_security_level=encrypt +  -o tls_preempt_cipherlist=yes +${smtpd_relay_restrictions}  -o smtpd_recipient_restrictions=\$smtps_recipient_restrictions +  -o smtpd_helo_restrictions=\$smtps_helo_restrictions +  -o smtpd_client_restrictions= +  -o cleanup_service_name=clean_smtps +clean_smtps   unix  n - n - 0 cleanup +  -o header_checks=pcre:/etc/postfix/checks/rewrite_openpgp_headers,pcre:/etc/postfix/checks/received_anon" + +  class { 'postfix': +    preseed             => true, +    root_mail_recipient => $root_mail_recipient, +    smtp_listen         => 'all', +    mastercf_tail       => $mastercf_tail, +    use_postscreen      => 'yes', +    require             => [ +      Class['Site_config::X509::Key'], +      Class['Site_config::X509::Cert'], +      Class['Site_config::X509::Client_ca::Key'], +      Class['Site_config::X509::Client_ca::Ca'], +      User['leap-mx'] ] +  } +} diff --git a/puppet/modules/site_postfix/manifests/mx/checks.pp b/puppet/modules/site_postfix/manifests/mx/checks.pp new file mode 100644 index 00000000..f406ad34 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/checks.pp @@ -0,0 +1,23 @@ +class site_postfix::mx::checks { + +  file { +    '/etc/postfix/checks': +      ensure  => directory, +      mode    => '0755', +      owner   => root, +      group   => postfix, +      require => Package['postfix']; + +    '/etc/postfix/checks/helo_checks': +      content => template('site_postfix/checks/helo_access.erb'), +      mode    => '0644', +      owner   => root, +      group   => root; +  } + +  exec { +    '/usr/sbin/postmap /etc/postfix/checks/helo_checks': +      refreshonly => true, +      subscribe   => File['/etc/postfix/checks/helo_checks']; +  } +} diff --git a/puppet/modules/site_postfix/manifests/mx/received_anon.pp b/puppet/modules/site_postfix/manifests/mx/received_anon.pp new file mode 100644 index 00000000..51ba3faa --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/received_anon.pp @@ -0,0 +1,13 @@ +# Anonymize the user's home IP from the email headers (Feature #3866)  +class site_postfix::mx::received_anon { + +  package { 'postfix-pcre': ensure => installed, require => Package['postfix'] } + +  file { '/etc/postfix/checks/received_anon': +    source => 'puppet:///modules/site_postfix/checks/received_anon', +    mode   => '0644', +    owner  => root, +    group  => root, +    notify => Service['postfix'] +  } +} diff --git a/puppet/modules/site_postfix/manifests/mx/rewrite_openpgp_header.pp b/puppet/modules/site_postfix/manifests/mx/rewrite_openpgp_header.pp new file mode 100644 index 00000000..71f945b8 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/rewrite_openpgp_header.pp @@ -0,0 +1,11 @@ +class site_postfix::mx::rewrite_openpgp_header { +  $mx             = hiera('mx') +  $correct_domain = $mx['key_lookup_domain'] + +  file { '/etc/postfix/checks/rewrite_openpgp_headers': +    content => template('site_postfix/checks/rewrite_openpgp_headers.erb'), +    mode    => '0644', +    owner   => root, +    group   => root; +  } +} diff --git a/puppet/modules/site_postfix/manifests/mx/smtp_auth.pp b/puppet/modules/site_postfix/manifests/mx/smtp_auth.pp new file mode 100644 index 00000000..afa70527 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/smtp_auth.pp @@ -0,0 +1,6 @@ +class site_postfix::mx::smtp_auth { + +  postfix::config { +    'smtpd_tls_ask_ccert': value => 'yes'; +  } +} diff --git a/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp b/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp new file mode 100644 index 00000000..c93c3ba2 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/smtp_tls.pp @@ -0,0 +1,43 @@ +# configure smtp tls +class site_postfix::mx::smtp_tls { + +  include site_config::x509::ca +  include x509::variables +  $cert_name = hiera('name') +  $ca_path   = "${x509::variables::local_CAs}/${site_config::params::ca_name}.crt" +  $cert_path = "${x509::variables::certs}/${site_config::params::cert_name}.crt" +  $key_path  = "${x509::variables::keys}/${site_config::params::cert_name}.key" + +  include site_config::x509::cert +  include site_config::x509::key + +  # smtp TLS +  postfix::config { +    'smtp_use_tls':        value  => 'yes'; +    'smtp_tls_CApath':     value  => '/etc/ssl/certs/'; +    'smtp_tls_CAfile':     value  => $ca_path; +    'smtp_tls_cert_file':  value  => $cert_path; +    'smtp_tls_key_file':   value  => $key_path; +    'smtp_tls_loglevel':   value  => '1'; +    'smtp_tls_exclude_ciphers': +      value => 'aNULL, MD5, DES'; +    # upstream default is md5 (since 2.5 and older used it), we force sha1 +    'smtp_tls_fingerprint_digest': +      value => 'sha1'; +    'smtp_tls_session_cache_database': +      value => "btree:\${data_directory}/smtp_cache"; +    # see issue #4011 +    'smtp_tls_protocols': +      value => '!SSLv2, !SSLv3'; +    'smtp_tls_mandatory_protocols': +      value => '!SSLv2, !SSLv3'; +    'tls_ssl_options': +      value => 'NO_COMPRESSION'; +    # We can switch between the different postfix internal list of ciphers by +    # using smtpd_tls_ciphers.  For server-to-server connections we leave this +    # at its default because of opportunistic encryption combined with many mail +    # servers only support outdated protocols and ciphers and if we are too +    # strict with required ciphers, then connections *will* fall-back to +    # plain-text. Bad ciphers are still better than plain text transmission. +  } +} diff --git a/puppet/modules/site_postfix/manifests/mx/smtpd_checks.pp b/puppet/modules/site_postfix/manifests/mx/smtpd_checks.pp new file mode 100644 index 00000000..291d7ee4 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/smtpd_checks.pp @@ -0,0 +1,36 @@ +# smtpd checks for incoming mail on smtp port 25 and +# mail sent via the bitmask client using smtps port 465 +class site_postfix::mx::smtpd_checks { + +  postfix::config { +    'smtpd_helo_required': +      value => 'yes'; +    'checks_dir': +      value => '$config_directory/checks'; +    'smtpd_client_restrictions': +      value => "permit_mynetworks,${site_postfix::mx::rbls},permit"; +    'smtpd_data_restrictions': +      value => 'permit_mynetworks, reject_unauth_pipelining, permit'; +    'smtpd_delay_reject': +      value => 'yes'; +    'smtpd_helo_restrictions': +      value => 'permit_mynetworks, reject_invalid_helo_hostname, reject_non_fqdn_helo_hostname, check_helo_access hash:$checks_dir/helo_checks, permit'; +    'smtpd_recipient_restrictions': +      value => 'reject_unknown_recipient_domain, permit_mynetworks, check_recipient_access tcp:localhost:2244, reject_unauth_destination, permit'; + +    # permit_tls_clientcerts will lookup client cert fingerprints from the tcp +    # lookup on port 2424 (based on what is configured in relay_clientcerts +    # paramter, see site_postfix::mx postfix::config resource) to determine +    # if a client is allowed to relay mail through us. This enables us to +    # disable a user by removing their valid client cert (#3634) +    'smtps_recipient_restrictions': +      value => 'permit_tls_clientcerts, check_recipient_access tcp:localhost:2244, reject_unauth_destination, permit'; +    'smtps_relay_restrictions': +      value => 'permit_mynetworks, permit_tls_clientcerts, defer_unauth_destination'; +    'smtps_helo_restrictions': +      value => 'permit_mynetworks, check_helo_access hash:$checks_dir/helo_checks, permit'; +    'smtpd_sender_restrictions': +      value => 'permit_mynetworks, reject_non_fqdn_sender, reject_unknown_sender_domain, permit'; +    } + +} diff --git a/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp b/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp new file mode 100644 index 00000000..66297f55 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/smtpd_tls.pp @@ -0,0 +1,69 @@ +# configure smtpd tls +class site_postfix::mx::smtpd_tls { + +  include x509::variables +  $ca_path   = "${x509::variables::local_CAs}/${site_config::params::client_ca_name}.crt" +  $cert_path = "${x509::variables::certs}/${site_config::params::cert_name}.crt" +  $key_path  = "${x509::variables::keys}/${site_config::params::cert_name}.key" + + +  postfix::config { +    'smtpd_use_tls':        value  => 'yes'; +    'smtpd_tls_CAfile':     value  => $ca_path; +    'smtpd_tls_cert_file':  value  => $cert_path; +    'smtpd_tls_key_file':   value  => $key_path; +    'smtpd_tls_ask_ccert':  value  => 'yes'; +    'smtpd_tls_received_header': +      value => 'yes'; +    'smtpd_tls_security_level': +      value  => 'may'; +    'smtpd_tls_eecdh_grade': +      value => 'ultra'; +    'smtpd_tls_session_cache_database': +      value => "btree:\${data_directory}/smtpd_scache"; +    # see issue #4011 +    'smtpd_tls_mandatory_protocols': +      value => '!SSLv2, !SSLv3'; +    'smtpd_tls_protocols': +      value => '!SSLv2, !SSLv3'; +    # For connections to MUAs, TLS is mandatory and the ciphersuite is modified. +    # MX and SMTP client configuration +    'smtpd_tls_mandatory_ciphers': +      value => 'high'; +    'tls_high_cipherlist': +      value => 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!RC4:!MD5:!PSK!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; +  } + +  # Setup DH parameters +  # Instead of using the dh parameters that are created by leap cli, it is more +  # secure to generate new parameter files that will only be used for postfix, +  # for each machine + +  include site_config::packages::gnutls + +  # Note, the file name is called dh_1024.pem, but we are generating 2048bit dh +  # parameters Neither Postfix nor OpenSSL actually care about the size of the +  # prime in "smtpd_tls_dh1024_param_file".  You can make it 2048 bits + +  exec { 'certtool-postfix-gendh': +    command => 'certtool --generate-dh-params --bits 2048 --outfile /etc/postfix/smtpd_tls_dh_param.pem', +    user    => root, +    group   => root, +    creates => '/etc/postfix/smtpd_tls_dh_param.pem', +    require => [ Package['gnutls-bin'], Package['postfix'] ] +  } + +  # Make sure the dh params file has correct ownership and mode +  file { +    '/etc/postfix/smtpd_tls_dh_param.pem': +      owner   => root, +      group   => root, +      mode    => '0600', +      require => Exec['certtool-postfix-gendh']; +  } + +  postfix::config { 'smtpd_tls_dh1024_param_file': +    value   => '/etc/postfix/smtpd_tls_dh_param.pem', +    require => File['/etc/postfix/smtpd_tls_dh_param.pem'] +  } +} diff --git a/puppet/modules/site_postfix/manifests/mx/static_aliases.pp b/puppet/modules/site_postfix/manifests/mx/static_aliases.pp new file mode 100644 index 00000000..9cd7ca02 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/mx/static_aliases.pp @@ -0,0 +1,88 @@ +# +# Defines static, hard coded aliases that are not in the database. +# These aliases take precedence over the database aliases. +# +# There are three classes of reserved names: +# +# (1) forbidden_usernames: +#     Some usernames are forbidden and cannot be registered. +#     this is defined in node property webapp.forbidden_usernames +#     This is enforced by the webapp. +# +# (2) public aliases: +#     Some aliases for root, and are publicly exposed so that anyone +#     can deliver mail to them. For example, postmaster. +#     These are implemented in the virtual alias map, which takes +#     precedence over the local alias map. +# +# (3) local aliases: +#     Some aliases are only available locally: mail can be delivered +#     to the alias if the mail originates from the local host, or is +#     hostname qualified, but otherwise it will be rejected. +#     These are implemented in the local alias map. +# +# The alias for local 'root' is defined elsewhere. In this file, we +# define the virtual 'root@domain' (which can be overwritten by +# defining an entry for root in node property mx.aliases). +# + +class site_postfix::mx::static_aliases { + +  $mx = hiera('mx') +  $root_recipients = hiera('contacts') + +  # +  # LOCAL ALIASES +  # + +  # NOTE: if you remove one of these, they will still appear in the +  # /etc/aliases file +  $local_aliases = [ +    'admin', 'administrator', 'bin', 'cron', 'games', 'ftp', 'lp', 'maildrop', +    'mysql', 'news', 'nobody', 'noc', 'postgresql', 'ssladmin', 'sys', +    'usenet', 'uucp', 'www', 'www-data', 'leap-mx' +  ] + +  postfix::mailalias { +    $local_aliases: +      ensure    => present, +      recipient => 'root' +  } + +  # +  # PUBLIC ALIASES +  # + +  $public_aliases = $mx['aliases'] + +  $default_public_aliases = { +    'root'          => $root_recipients, +    'abuse'         => 'postmaster', +    'arin-admin'    => 'root', +    'certmaster'    => 'hostmaster', +    'domainadmin'   => 'hostmaster', +    'hostmaster'    => 'root', +    'mailer-daemon' => 'postmaster', +    'postmaster'    => 'root', +    'security'      => 'root', +    'webmaster'     => 'hostmaster', +  } + +  $aliases = merge($default_public_aliases, $public_aliases) + +  exec { 'postmap_virtual_aliases': +    command     => '/usr/sbin/postmap /etc/postfix/virtual-aliases', +    refreshonly => true, +    user        => root, +    group       => root, +    require     => Package['postfix'], +    subscribe   => File['/etc/postfix/virtual-aliases'] +  } +  file { '/etc/postfix/virtual-aliases': +    content => template('site_postfix/virtual-aliases.erb'), +    owner   => root, +    group   => root, +    mode    => '0600', +    require => Package['postfix'] +  } +} diff --git a/puppet/modules/site_postfix/manifests/satellite.pp b/puppet/modules/site_postfix/manifests/satellite.pp new file mode 100644 index 00000000..5725e6b8 --- /dev/null +++ b/puppet/modules/site_postfix/manifests/satellite.pp @@ -0,0 +1,47 @@ +class site_postfix::satellite { + +  $root_mail_recipient = hiera ('contacts') +  $mail                = hiera ('mail') +  $relayhost           = $mail['smarthost'] +  $cert_name           = hiera('name') + +  class { '::postfix::satellite': +    relayhost           => $relayhost, +    root_mail_recipient => $root_mail_recipient +  } + +  # There are special conditions for satellite hosts that will make them not be +  # able to contact their relayhost: +  # +  # 1. they are on openstack/amazon/PC and are on the same cluster as the relay +  # host, the MX lookup for the relay host will use the public IP, which cannot +  # be contacted +  # +  # 2. When a domain is used that is not in DNS, because it is internal, +  # a testing domain, etc. eg. a .local domain cannot be looked up in DNS +  # +  # to resolve this, so the satellite can contact the relayhost, we need to set +  # the http://www.postfix.org/postconf.5.html#smtp_host_lookup to be 'native' +  # which will cause the lookup to use the native naming service +  # (nsswitch.conf), which typically defaults to 'files, dns' allowing the +  # /etc/hosts to be consulted first, then DNS if the entry doesn't exist. +  # +  # NOTE: this will make it not possible to enable DANE support through DNSSEC +  # with http://www.postfix.org/postconf.5.html#smtp_dns_support_level - but +  # this parameter is not available until 2.11. If this ends up being important +  # we could also make this an optional parameter for providers without +  # dns / local domains + +  postfix::config { +    'smtp_host_lookup': +      value => 'native'; + +    # Note: we are setting this here, instead of in site_postfix::mx::smtp_tls +    # because the mx server has to have a different value +    'smtp_tls_security_level': +      value => 'encrypt'; +  } + +  include site_postfix::mx::smtp_tls + +} diff --git a/puppet/modules/site_postfix/templates/checks/helo_access.erb b/puppet/modules/site_postfix/templates/checks/helo_access.erb new file mode 100644 index 00000000..bac2c45a --- /dev/null +++ b/puppet/modules/site_postfix/templates/checks/helo_access.erb @@ -0,0 +1,21 @@ +# THIS FILE IS MANAGED BY PUPPET +# To make changes to this file, please edit your platform directory under +# puppet/modules/site_postfix/templates/checks/helo_access.erb and then deploy + +# The format of this file is the HELO/EHLO domain followed by an action. +# The action could be OK to allow it, REJECT to reject it, or a custom +# status code and message. Any lines that are prefixed by an octothorpe (#) +# will be considered comments. + +# Some examples: +# +# Reject anyone that HELO's with foobar: +# foobar REJECT +# +# Allow the switches to skip this check: +# switch1 OK +# switch2 OK + +# Reject anybody that HELO's as being in our own domain(s) +# anyone who identifies themselves as us is a virus/spammer +<%= @domain %> 554 You are not in domain <%= @domain %> diff --git a/puppet/modules/site_postfix/templates/checks/rewrite_openpgp_headers.erb b/puppet/modules/site_postfix/templates/checks/rewrite_openpgp_headers.erb new file mode 100644 index 00000000..7af14f7d --- /dev/null +++ b/puppet/modules/site_postfix/templates/checks/rewrite_openpgp_headers.erb @@ -0,0 +1,13 @@ +# THIS FILE IS MANAGED BY PUPPET +# +# This will replace the OpenPGP header that the client adds, because it is +# sometimes incorrect (due to the client not always knowing what the proper URL +# is for the webapp). +# e.g. This will rewrite this header: +# OpenPGP: id=4C0E01CD50E2F653; url="https://leap.se/key/elijah"; preference="signencrypt +# with this replacement: +# OpenPGP: id=4C0E01CD50E2F653; url="https://user.leap.se/key/elijah"; preference="signencrypt +# +# Note: whitespace in the pattern is represented by [[:space:]] to avoid these warnings from postmap: +# "record is in "key: value" format; is this an alias file?" and "duplicate entry" +/^(OpenPGP:[[:space:]]id=[[:alnum:]]+;[[:space:]]url="https:\/\/)<%= @domain %>(\/key\/[[:alpha:]]+";.*)/i REPLACE ${1}<%= @correct_domain %>${2} diff --git a/puppet/modules/site_postfix/templates/virtual-aliases.erb b/puppet/modules/site_postfix/templates/virtual-aliases.erb new file mode 100644 index 00000000..8373de97 --- /dev/null +++ b/puppet/modules/site_postfix/templates/virtual-aliases.erb @@ -0,0 +1,21 @@ +# +# This file is managed by puppet. +# +# These virtual aliases take precedence over all other aliases. +# + +# +# enable these virtual domains: +# +<%= @domain %> enabled +<%- @aliases.keys.map {|addr| addr.split('@')[1] }.compact.sort.uniq.each do |virt_domain| -%> +<%= virt_domain %> enabled +<%- end %> + +# +# virtual aliases: +# +<%- @aliases.keys.sort.each do |from| -%> +<%-   full_address = from =~ /@/ ? from : from + "@" + @domain -%> +<%= full_address %> <%= [@aliases[from]].flatten.map{|a| a =~ /@/ ? a : a + "@" + @domain}.join(', ') %> +<%- end -%> diff --git a/puppet/modules/site_rsyslog/templates/client.conf.erb b/puppet/modules/site_rsyslog/templates/client.conf.erb new file mode 100644 index 00000000..7f94759d --- /dev/null +++ b/puppet/modules/site_rsyslog/templates/client.conf.erb @@ -0,0 +1,134 @@ + +# An "In-Memory Queue" is created for remote logging. +$WorkDirectory <%= scope.lookupvar('rsyslog::spool_dir') -%>    # where to place spool files +$ActionQueueFileName queue      # unique name prefix for spool files +$ActionQueueMaxDiskSpace <%= scope.lookupvar('rsyslog::client::spool_size') -%>     # spool space limit (use as much as possible) +$ActionQueueSaveOnShutdown on   # save messages to disk on shutdown +$ActionQueueType LinkedList     # run asynchronously +$ActionResumeRetryCount -1      # infinety retries if host is down +<% if scope.lookupvar('rsyslog::client::log_templates') and ! scope.lookupvar('rsyslog::client::log_templates').empty?-%> + +# Define custom logging templates +<% scope.lookupvar('rsyslog::client::log_templates').flatten.compact.each do |log_template| -%> +$template <%= log_template['name'] %>,"<%= log_template['template'] %>" +<% end -%> +<% end -%> +<% if scope.lookupvar('rsyslog::client::actionfiletemplate') -%> + +# Using specified format for default logging format: +$ActionFileDefaultTemplate <%= scope.lookupvar('rsyslog::client::actionfiletemplate') %> +<% else -%> + +#Using default format for default logging format: +$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat +<% end -%> +<% if scope.lookupvar('rsyslog::client::ssl') -%> + +# Setup SSL connection. +# CA/Cert +$DefaultNetStreamDriverCAFile <%= scope.lookupvar('rsyslog::client::ssl_ca') %> + +# Connection settings. +$DefaultNetstreamDriver gtls +$ActionSendStreamDriverMode 1 +$ActionSendStreamDriverAuthMode anon +<% end -%> +<% if scope.lookupvar('rsyslog::client::remote_servers')  -%> + +<% scope.lookupvar('rsyslog::client::remote_servers').flatten.compact.each do |server| -%> +<% if server['pattern'] and server['pattern'] != ''-%> +<% pattern = server['pattern'] -%> +<% else -%> +<% pattern = '*.*' -%> +<% end -%> +<% if server['protocol'] == 'TCP' or server['protocol'] == 'tcp'-%> +<% protocol = '@@' -%> +<% protocol_type = 'TCP' -%> +<% else -%> +<% protocol = '@' -%> +<% protocol_type = 'UDP' -%> +<% end -%> +<% if server['host'] and server['host'] != ''-%> +<% host = server['host'] -%> +<% else -%> +<% host = 'localhost' -%> +<% end -%> +<% if server['port'] and server['port'] != ''-%> +<% port = server['port'] -%> +<% else -%> +<% port = '514' -%> +<% end -%> +<% if server['format'] -%> +<% format = ";#{server['format']}" -%> +<% format_type = server['format'] -%> +<% else -%> +<% format = '' -%> +<% format_type = 'the default' -%> +<% end -%> +# Sending logs that match <%= pattern %> to <%= host %> via <%= protocol_type %> on <%= port %> using <%=format_type %> format. +<%= pattern %> <%= protocol %><%= host %>:<%= port %><%= format %> +<% end -%> +<% elsif scope.lookupvar('rsyslog::client::log_remote') -%> + +# Log to remote syslog server using <%= scope.lookupvar('rsyslog::client::remote_type') %> +<% if scope.lookupvar('rsyslog::client::remote_type') == 'tcp' -%> +*.* @@<%= scope.lookupvar('rsyslog::client::server') -%>:<%= scope.lookupvar('rsyslog::client::port') -%>;<%= scope.lookupvar('remote_forward_format') -%> +<% else -%> +*.* @<%= scope.lookupvar('rsyslog::client::server') -%>:<%= scope.lookupvar('rsyslog::client::port') -%>;<%= scope.lookupvar('remote_forward_format') -%> +<% end -%> +<% end -%> +<% if scope.lookupvar('rsyslog::client::log_auth_local') or scope.lookupvar('rsyslog::client::log_local') -%> + +# Logging locally. + +<% if scope.lookupvar('rsyslog::log_style') == 'debian' -%> +# Log auth messages locally +.*;auth,authpriv.none;mail.none -/var/log/syslog +<% elsif scope.lookupvar('rsyslog::log_style') == 'redhat' -%> +# Log auth messages locally +auth,authpriv.*                 /var/log/secure +<% end -%> +<% end -%> +<% if scope.lookupvar('rsyslog::client::log_local') -%> +<% if scope.lookupvar('rsyslog::log_style') == 'debian' -%> +# First some standard log files.  Log by facility. +# +*.*;auth,authpriv.none         -/var/log/syslog +cron.*                          /var/log/cron.log +daemon.*                       -/var/log/daemon.log +kern.*                         -/var/log/kern.log +mail.*                         -/var/log/mail.log +user.*                         -/var/log/user.log + +# +# Some "catch-all" log files. +# +*.=debug;\ +       auth,authpriv.none;\ +       news.none;mail.none     -/var/log/debug +*.=info;*.=notice;*.=warn;\ +       auth,authpriv.none;\ +       cron,daemon.none;\ +       mail,news.none          -/var/log/messages + +# Log anything (except mail) of level info or higher. +# Don't log private authentication messages! +*.info;mail.none;authpriv.none;cron.none                /var/log/messages + +# Log cron stuff +cron.*                         /var/log/cron + +# Everybody gets emergency messages +<% if @rsyslog_version and @rsyslog_version.split('.')[0].to_i >= 8 -%> +*.emerg       :omusrmsg:* +<% else -%> +*.emerg				* +<% end -%> + +# Save boot messages also to boot.log +local7.*                       -/var/log/boot.log +<% end -%> +<% end -%> + + + diff --git a/puppet/modules/site_shorewall/files/Debian/shorewall.service b/puppet/modules/site_shorewall/files/Debian/shorewall.service new file mode 100644 index 00000000..ec250ef1 --- /dev/null +++ b/puppet/modules/site_shorewall/files/Debian/shorewall.service @@ -0,0 +1,23 @@ +# +#     The Shoreline Firewall (Shorewall) Packet Filtering Firewall +# +#     Copyright 2011 Jonathan Underwood <jonathan.underwood@gmail.com> +#     Copyright 2015 Tom Eastep <teastep@shorewall.net> +# +[Unit] +Description=Shorewall IPv4 firewall +Wants=network-online.target +After=network-online.target +Conflicts=iptables.service firewalld.service + +[Service] +Type=oneshot +RemainAfterExit=yes +EnvironmentFile=-/etc/default/shorewall +StandardOutput=syslog +ExecStart=/sbin/shorewall $OPTIONS start $STARTOPTIONS +ExecStop=/sbin/shorewall $OPTIONS stop +ExecReload=/sbin/shorewall $OPTIONS reload $RELOADOPTIONS + +[Install] +WantedBy=basic.target diff --git a/puppet/modules/site_shorewall/manifests/defaults.pp b/puppet/modules/site_shorewall/manifests/defaults.pp new file mode 100644 index 00000000..ceb17868 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/defaults.pp @@ -0,0 +1,86 @@ +class site_shorewall::defaults { + +  include shorewall +  include site_config::params + +  # be safe for development +  # if ( $::site_config::params::environment == 'local' ) { +  #  $shorewall_startup='0' +  # } + +  # If you want logging: +  shorewall::params { +    'LOG': value => 'debug'; +  } + +  shorewall::zone {'net': type => 'ipv4'; } + +  # define interfaces +  shorewall::interface { $site_config::params::interface: +    zone      => 'net', +    options   => 'tcpflags,blacklist,nosmurfs'; +  } + +  shorewall::policy { +    'fw-to-all': +      sourcezone      => 'fw', +      destinationzone => 'all', +      policy          => 'ACCEPT', +      order           => 100; +    'all-to-all': +      sourcezone      => 'all', +      destinationzone => 'all', +      policy          => 'DROP', +      order           => 200; +  } + +  shorewall::rule { +      # ping party +      'all2all-ping': +        source      => 'all', +        destination => 'all', +        action      => 'Ping(ACCEPT)', +        order       => 200; +  } + +  package { 'shorewall-init': +    ensure => installed +  } + +  include ::systemd +  file { '/etc/systemd/system/shorewall.service': +    ensure  => file, +    owner   => 'root', +    group   => 'root', +    mode    => '0644', +    source  => 'puppet:///modules/site_shorewall/Debian/shorewall.service', +    require => Package['shorewall'], +    notify  => Service['shorewall'], +    } ~> +    Exec['systemctl-daemon-reload'] + +  augeas { +    # stop instead of clear firewall on shutdown +    'shorewall_SAFESTOP': +      changes => 'set /files/etc/shorewall/shorewall.conf/SAFESTOP Yes', +      lens    => 'Shellvars.lns', +      incl    => '/etc/shorewall/shorewall.conf', +      require => Package['shorewall'], +      notify  => Service['shorewall']; +    # require that the interface exist +    'shorewall_REQUIRE_INTERFACE': +      changes => 'set /files/etc/shorewall/shorewall.conf/REQUIRE_INTERFACE Yes', +      lens    => 'Shellvars.lns', +      incl    => '/etc/shorewall/shorewall.conf', +      require => Package['shorewall'], +      notify  => Service['shorewall']; +    # configure shorewall-init +    'shorewall-init': +      changes => 'set /files/etc/default/shorewall-init/PRODUCTS shorewall', +      lens    => 'Shellvars.lns', +      incl    => '/etc/default/shorewall-init', +      require => [ Package['shorewall-init'], Service['shorewall'] ] +  } + +  include site_shorewall::sshd +} diff --git a/puppet/modules/site_shorewall/manifests/dnat.pp b/puppet/modules/site_shorewall/manifests/dnat.pp new file mode 100644 index 00000000..a73294cc --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/dnat.pp @@ -0,0 +1,19 @@ +define site_shorewall::dnat ( +  $source, +  $destination, +  $proto, +  $destinationport, +  $originaldest ) { + + +  shorewall::rule { +    "dnat_${name}_${destinationport}": +      action          => 'DNAT', +      source          => $source, +      destination     => $destination, +      proto           => $proto, +      destinationport => $destinationport, +      originaldest    => $originaldest, +      order           => 200 +  } +} diff --git a/puppet/modules/site_shorewall/manifests/dnat_rule.pp b/puppet/modules/site_shorewall/manifests/dnat_rule.pp new file mode 100644 index 00000000..f9fbe950 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/dnat_rule.pp @@ -0,0 +1,50 @@ +define site_shorewall::dnat_rule { + +  $port = $name +  if $port != 1194 { +    if $site_openvpn::openvpn_allow_unlimited { +      shorewall::rule { +          "dnat_tcp_port_${port}": +            action          => 'DNAT', +            source          => 'net', +            destination     => "\$FW:${site_openvpn::unlimited_gateway_address}:1194", +            proto           => 'tcp', +            destinationport => $port, +            originaldest    => $site_openvpn::unlimited_gateway_address, +            order           => 100; +      } +      shorewall::rule { +          "dnat_udp_port_${port}": +            action          => 'DNAT', +            source          => 'net', +            destination     => "\$FW:${site_openvpn::unlimited_gateway_address}:1194", +            proto           => 'udp', +            destinationport => $port, +            originaldest    => $site_openvpn::unlimited_gateway_address, +            order           => 100; +      } +    } +    if $site_openvpn::openvpn_allow_limited { +      shorewall::rule { +          "dnat_free_tcp_port_${port}": +            action          => 'DNAT', +            source          => 'net', +            destination     => "\$FW:${site_openvpn::limited_gateway_address}:1194", +            proto           => 'tcp', +            destinationport => $port, +            originaldest    => $site_openvpn::unlimited_gateway_address, +            order           => 100; +      } +      shorewall::rule { +          "dnat_free_udp_port_${port}": +            action          => 'DNAT', +            source          => 'net', +            destination     => "\$FW:${site_openvpn::limited_gateway_address}:1194", +            proto           => 'udp', +            destinationport => $port, +            originaldest    => $site_openvpn::unlimited_gateway_address, +            order           => 100; +      } +    } +  } +} diff --git a/puppet/modules/site_shorewall/manifests/eip.pp b/puppet/modules/site_shorewall/manifests/eip.pp new file mode 100644 index 00000000..8fbba658 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/eip.pp @@ -0,0 +1,92 @@ +class site_shorewall::eip { + +  include site_shorewall::defaults +  include site_config::params +  include site_shorewall::ip_forward + +  # define macro for incoming services +  file { '/etc/shorewall/macro.leap_eip': +    content => "PARAM   -       -       tcp     1194 +    PARAM   -       -       udp     1194 +    ", +    notify  => Service['shorewall'], +    require => Package['shorewall'] +  } + +  shorewall::interface { +    'tun0': +      zone    => 'eip', +      options => 'tcpflags,blacklist,nosmurfs'; +    'tun1': +      zone    => 'eip', +      options => 'tcpflags,blacklist,nosmurfs'; +    'tun2': +      zone    => 'eip', +      options => 'tcpflags,blacklist,nosmurfs'; +    'tun3': +      zone    => 'eip', +      options => 'tcpflags,blacklist,nosmurfs'; +  } + +  shorewall::zone { +    'eip': +      type => 'ipv4'; +  } + +  $interface = $site_config::params::interface + +  shorewall::masq { +    "${interface}_unlimited_tcp": +      interface => $interface, +      source    => "${site_openvpn::openvpn_unlimited_tcp_network_prefix}.0/${site_openvpn::openvpn_unlimited_tcp_cidr}"; +    "${interface}_unlimited_udp": +      interface => $interface, +      source    => "${site_openvpn::openvpn_unlimited_udp_network_prefix}.0/${site_openvpn::openvpn_unlimited_udp_cidr}"; +  } +  if ! $::ec2_instance_id { +    shorewall::masq { +      "${interface}_limited_tcp": +        interface => $interface, +        source    => "${site_openvpn::openvpn_limited_tcp_network_prefix}.0/${site_openvpn::openvpn_limited_tcp_cidr}"; +      "${interface}_limited_udp": +        interface => $interface, +        source    => "${site_openvpn::openvpn_limited_udp_network_prefix}.0/${site_openvpn::openvpn_limited_udp_cidr}"; +    } +  } + +  shorewall::policy { +    'eip-to-all': +      sourcezone      => 'eip', +      destinationzone => 'all', +      policy          => 'ACCEPT', +      order           => 100; +  } + +  shorewall::rule { +    'net2fw-openvpn': +      source      => 'net', +      destination => '$FW', +      action      => 'leap_eip(ACCEPT)', +      order       => 200; + +    'block_eip_dns_udp': +      action          => 'REJECT', +      source          => 'eip', +      destination     => 'net', +      proto           => 'udp', +      destinationport => 'domain', +      order           => 300; + +    'block_eip_dns_tcp': +      action          => 'REJECT', +      source          => 'eip', +      destination     => 'net', +      proto           => 'tcp', +      destinationport => 'domain', +      order           => 301; +  } + +  # create dnat rule for each port +  site_shorewall::dnat_rule { $site_openvpn::openvpn_ports: } + +} diff --git a/puppet/modules/site_shorewall/manifests/ip_forward.pp b/puppet/modules/site_shorewall/manifests/ip_forward.pp new file mode 100644 index 00000000..d53ee8a5 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/ip_forward.pp @@ -0,0 +1,10 @@ +class site_shorewall::ip_forward { +  include augeas +  augeas { 'enable_ip_forwarding': +    changes => 'set /files/etc/shorewall/shorewall.conf/IP_FORWARDING Yes', +    lens    => 'Shellvars.lns', +    incl    => '/etc/shorewall/shorewall.conf', +    notify  => Service[shorewall], +    require => [ Class[augeas], Package[shorewall] ]; +  } +} diff --git a/puppet/modules/site_shorewall/manifests/monitor.pp b/puppet/modules/site_shorewall/manifests/monitor.pp new file mode 100644 index 00000000..f4ed4f7c --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/monitor.pp @@ -0,0 +1,8 @@ +class site_shorewall::monitor { + +  include site_shorewall::defaults +  include site_shorewall::service::http +  include site_shorewall::service::https + + +} diff --git a/puppet/modules/site_shorewall/manifests/mx.pp b/puppet/modules/site_shorewall/manifests/mx.pp new file mode 100644 index 00000000..332f164e --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/mx.pp @@ -0,0 +1,24 @@ +class site_shorewall::mx { + +  include site_shorewall::defaults + +  $smtpd_ports = '25,465,587' + +  # define macro for incoming services +  file { '/etc/shorewall/macro.leap_mx': +    content => "PARAM   -       -       tcp    ${smtpd_ports} ", +    notify  => Service['shorewall'], +    require => Package['shorewall'] +  } + + +  shorewall::rule { +      'net2fw-mx': +        source      => 'net', +        destination => '$FW', +        action      => 'leap_mx(ACCEPT)', +        order       => 200; +  } + +  include site_shorewall::service::smtp +} diff --git a/puppet/modules/site_shorewall/manifests/obfsproxy.pp b/puppet/modules/site_shorewall/manifests/obfsproxy.pp new file mode 100644 index 00000000..75846705 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/obfsproxy.pp @@ -0,0 +1,25 @@ +# configure shorewell for obfsproxy +class site_shorewall::obfsproxy { + +  include site_shorewall::defaults + +  $obfsproxy    = hiera('obfsproxy') +  $scramblesuit = $obfsproxy['scramblesuit'] +  $scram_port   = $scramblesuit['port'] + +  # define macro for incoming services +  file { '/etc/shorewall/macro.leap_obfsproxy': +    content => "PARAM   -       -       tcp    ${scram_port} ", +    notify  => Service['shorewall'], +    require => Package['shorewall'] +  } + +  shorewall::rule { +      'net2fw-obfs': +        source      => 'net', +        destination => '$FW', +        action      => 'leap_obfsproxy(ACCEPT)', +        order       => 200; +  } + +} diff --git a/puppet/modules/site_shorewall/manifests/service/http.pp b/puppet/modules/site_shorewall/manifests/service/http.pp new file mode 100644 index 00000000..74b874d5 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/service/http.pp @@ -0,0 +1,13 @@ +class site_shorewall::service::http { + +  include site_shorewall::defaults + +  shorewall::rule { +      'net2fw-http': +        source      => 'net', +        destination => '$FW', +        action      => 'HTTP(ACCEPT)', +        order       => 200; +  } + +} diff --git a/puppet/modules/site_shorewall/manifests/service/https.pp b/puppet/modules/site_shorewall/manifests/service/https.pp new file mode 100644 index 00000000..4a8b119c --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/service/https.pp @@ -0,0 +1,12 @@ +class site_shorewall::service::https { + +  include site_shorewall::defaults + +  shorewall::rule { +      'net2fw-https': +        source      => 'net', +        destination => '$FW', +        action      => 'HTTPS(ACCEPT)', +        order       => 200; +  } +} diff --git a/puppet/modules/site_shorewall/manifests/service/smtp.pp b/puppet/modules/site_shorewall/manifests/service/smtp.pp new file mode 100644 index 00000000..7fbdf14e --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/service/smtp.pp @@ -0,0 +1,13 @@ +class site_shorewall::service::smtp { + +  include site_shorewall::defaults + +  shorewall::rule { +      'fw2net-http': +        source      => '$FW', +        destination => 'net', +        action      => 'SMTP(ACCEPT)', +        order       => 200; +  } + +} diff --git a/puppet/modules/site_shorewall/manifests/service/webapp_api.pp b/puppet/modules/site_shorewall/manifests/service/webapp_api.pp new file mode 100644 index 00000000..d3a1aeed --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/service/webapp_api.pp @@ -0,0 +1,23 @@ +# configure shorewall for webapp api +class site_shorewall::service::webapp_api { + +  $api = hiera('api') +  $api_port = $api['port'] + +  # define macro for incoming services +  file { '/etc/shorewall/macro.leap_webapp_api': +    content => "PARAM   -       -       tcp    ${api_port} ", +    notify  => Service['shorewall'], +    require => Package['shorewall'] +  } + + +  shorewall::rule { +      'net2fw-webapp_api': +        source      => 'net', +        destination => '$FW', +        action      => 'leap_webapp_api(ACCEPT)', +        order       => 200; +  } + +} diff --git a/puppet/modules/site_shorewall/manifests/soledad.pp b/puppet/modules/site_shorewall/manifests/soledad.pp new file mode 100644 index 00000000..518d8689 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/soledad.pp @@ -0,0 +1,23 @@ +class site_shorewall::soledad { + +  $soledad      = hiera('soledad') +  $soledad_port = $soledad['port'] + +  include site_shorewall::defaults + +  # define macro for incoming services +  file { '/etc/shorewall/macro.leap_soledad': +    content => "PARAM   -       -       tcp    ${soledad_port}", +    notify  => Service['shorewall'], +    require => Package['shorewall'] +  } + +  shorewall::rule { +    'net2fw-soledad': +      source      => 'net', +      destination => '$FW', +      action      => 'leap_soledad(ACCEPT)', +      order       => 200; +  } +} + diff --git a/puppet/modules/site_shorewall/manifests/sshd.pp b/puppet/modules/site_shorewall/manifests/sshd.pp new file mode 100644 index 00000000..e2332592 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/sshd.pp @@ -0,0 +1,31 @@ +# configure shorewall for sshd +class site_shorewall::sshd { + +  $ssh_config     = hiera('ssh') +  $ssh_port       = $ssh_config['port'] + +  include shorewall + +  # define macro for incoming sshd +  file { '/etc/shorewall/macro.leap_sshd': +    content => "PARAM   -       -       tcp    ${ssh_port}", +    notify  => Service['shorewall'], +    require => Package['shorewall'] +  } + + +  shorewall::rule { +      # outside to server +      'net2fw-ssh': +        source      => 'net', +        destination => '$FW', +        action      => 'leap_sshd(ACCEPT)', +        order       => 200; +  } + +  # setup a routestopped rule to allow ssh when shorewall is stopped +  shorewall::routestopped { $site_config::params::interface: +    options => "-   tcp   ${ssh_port}" +  } + +} diff --git a/puppet/modules/site_shorewall/manifests/stunnel/client.pp b/puppet/modules/site_shorewall/manifests/stunnel/client.pp new file mode 100644 index 00000000..9a89a244 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/stunnel/client.pp @@ -0,0 +1,40 @@ +# +# Adds some firewall magic to the stunnel. +# +# Using DNAT, this firewall rule allow a locally running program +# to try to connect to the normal remote IP and remote port of the +# service on another machine, but have this connection magically +# routed through the locally running stunnel client. +# +# The network looks like this: +# +#   From the client's perspective: +# +#   |------- stunnel client --------------|    |---------- stunnel server -----------------------| +#    consumer app -> localhost:accept_port  ->  connect:connect_port -> localhost:original_port +# +#   From the server's perspective: +# +#   |------- stunnel client --------------|    |---------- stunnel server -----------------------| +#                                       ??  ->  *:accept_port -> localhost:connect_port -> service +# + +define site_shorewall::stunnel::client( +  $accept_port, +  $connect, +  $connect_port, +  $original_port) { + +  include site_shorewall::defaults + +  shorewall::rule { +    "stunnel_dnat_${name}": +      action          => 'DNAT', +      source          => '$FW', +      destination     => "\$FW:127.0.0.1:${accept_port}", +      proto           => 'tcp', +      destinationport => $original_port, +      originaldest    => $connect, +      order           => 200 +  } +} diff --git a/puppet/modules/site_shorewall/manifests/stunnel/server.pp b/puppet/modules/site_shorewall/manifests/stunnel/server.pp new file mode 100644 index 00000000..798cd631 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/stunnel/server.pp @@ -0,0 +1,22 @@ +# +# Allow all incoming connections to stunnel server port +# + +define site_shorewall::stunnel::server($port) { + +  include site_shorewall::defaults + +  file { "/etc/shorewall/macro.stunnel_server_${name}": +    content => "PARAM   -       -       tcp    ${port}", +    notify  => Service['shorewall'], +    require => Package['shorewall'] +  } +  shorewall::rule { +    "net2fw-stunnel-server-${name}": +      source      => 'net', +      destination => '$FW', +      action      => "stunnel_server_${name}(ACCEPT)", +      order       => 200; +  } + +}
\ No newline at end of file diff --git a/puppet/modules/site_shorewall/manifests/tor.pp b/puppet/modules/site_shorewall/manifests/tor.pp new file mode 100644 index 00000000..324b4844 --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/tor.pp @@ -0,0 +1,26 @@ +# configure shorewall for tor +class site_shorewall::tor { + +  include site_shorewall::defaults +  include site_shorewall::ip_forward + +  $tor_port = '9001' + +  # define macro for incoming services +  file { '/etc/shorewall/macro.leap_tor': +    content => "PARAM   -       -       tcp    ${tor_port} ", +    notify  => Service['shorewall'], +    require => Package['shorewall'] +  } + + +  shorewall::rule { +      'net2fw-tor': +        source      => 'net', +        destination => '$FW', +        action      => 'leap_tor(ACCEPT)', +        order       => 200; +  } + +  include site_shorewall::service::http +} diff --git a/puppet/modules/site_shorewall/manifests/webapp.pp b/puppet/modules/site_shorewall/manifests/webapp.pp new file mode 100644 index 00000000..a8d2aa5b --- /dev/null +++ b/puppet/modules/site_shorewall/manifests/webapp.pp @@ -0,0 +1,7 @@ +class site_shorewall::webapp { + +  include site_shorewall::defaults +  include site_shorewall::service::https +  include site_shorewall::service::http +  include site_shorewall::service::webapp_api +} diff --git a/puppet/modules/site_squid_deb_proxy/manifests/client.pp b/puppet/modules/site_squid_deb_proxy/manifests/client.pp new file mode 100644 index 00000000..27844270 --- /dev/null +++ b/puppet/modules/site_squid_deb_proxy/manifests/client.pp @@ -0,0 +1,5 @@ +class site_squid_deb_proxy::client { +  include squid_deb_proxy::client +  include site_shorewall::defaults +  include shorewall::rules::mdns +} diff --git a/puppet/modules/site_sshd/manifests/authorized_keys.pp b/puppet/modules/site_sshd/manifests/authorized_keys.pp new file mode 100644 index 00000000..a1fde3f6 --- /dev/null +++ b/puppet/modules/site_sshd/manifests/authorized_keys.pp @@ -0,0 +1,34 @@ +# We want to purge unmanaged keys from the authorized_keys file so that only +# keys added in the provider are valid. Any manually added keys will be +# overridden. +# +# In order to do this, we have to use a custom define to deploy the +# authorized_keys file because puppet's internal resource doesn't allow +# purging before populating this file. +# +# See the following for more information: +# https://tickets.puppetlabs.com/browse/PUP-1174 +# https://leap.se/code/issues/2990 +# https://leap.se/code/issues/3010 +# +define site_sshd::authorized_keys ($keys, $ensure = 'present', $home = '') { +  # This line allows default homedir based on $title variable. +  # If $home is empty, the default is used. +  $homedir = $home ? {'' => "/home/${title}", default => $home} +  $owner   = $ensure ? {'present' => $title, default => undef } +  $group   = $ensure ? {'present' => $title, default => undef } +  file { +    "${homedir}/.ssh": +      ensure  => 'directory', +      owner   => $title, +      group   => $title, +      mode    => '0700'; +    "${homedir}/.ssh/authorized_keys": +      ensure  => $ensure, +      owner   => $owner, +      group   => $group, +      mode    => '0600', +      require => File["${homedir}/.ssh"], +      content => template('site_sshd/authorized_keys.erb'); +  } +} diff --git a/puppet/modules/site_sshd/manifests/deploy_authorized_keys.pp b/puppet/modules/site_sshd/manifests/deploy_authorized_keys.pp new file mode 100644 index 00000000..97ca058f --- /dev/null +++ b/puppet/modules/site_sshd/manifests/deploy_authorized_keys.pp @@ -0,0 +1,9 @@ +class site_sshd::deploy_authorized_keys ( $keys ) { +  tag 'leap_authorized_keys' + +  site_sshd::authorized_keys {'root': +    keys => $keys, +    home => '/root' +  } + +} diff --git a/puppet/modules/site_sshd/manifests/init.pp b/puppet/modules/site_sshd/manifests/init.pp new file mode 100644 index 00000000..a9202da4 --- /dev/null +++ b/puppet/modules/site_sshd/manifests/init.pp @@ -0,0 +1,82 @@ +# configures sshd, mosh, authorized keys and known hosts +class site_sshd { +  $ssh        = hiera_hash('ssh') +  $ssh_config = $ssh['config'] +  $hosts      = hiera('hosts', '') + +  ## +  ## SETUP AUTHORIZED KEYS +  ## + +  $authorized_keys = $ssh['authorized_keys'] + +  class { 'site_sshd::deploy_authorized_keys': +    keys => $authorized_keys +  } + +  ## +  ## SETUP KNOWN HOSTS and SSH_CONFIG +  ## + +  file { +    '/etc/ssh/ssh_known_hosts': +      owner   => root, +      group   => root, +      mode    => '0644', +      content => template('site_sshd/ssh_known_hosts.erb'); + +    '/etc/ssh/ssh_config': +      owner   => root, +      group   => root, +      mode    => '0644', +      content => template('site_sshd/ssh_config.erb'); +  } + +  ## +  ## OPTIONAL MOSH SUPPORT +  ## + +  $mosh = $ssh['mosh'] + +  if $mosh['enabled'] { +    class { 'site_sshd::mosh': +      ensure => present, +      ports  => $mosh['ports'] +    } +  } +  else { +    class { 'site_sshd::mosh': +      ensure => absent +    } +  } + +  # we cannot use the 'hardened' parameter because leap_cli uses an +  # old net-ssh gem that is incompatible with the included +  # "KexAlgorithms curve25519-sha256@libssh.org", +  # see https://leap.se/code/issues/7591 +  # therefore we don't use it here, but include all other options +  # that would be applied by the 'hardened' parameter +  # not all options are available on wheezy +  if ( $::lsbdistcodename == 'wheezy' ) { +    $tail_additional_options = 'Ciphers aes256-ctr +MACs hmac-sha2-512,hmac-sha2-256,hmac-ripemd160' +  } else { +    $tail_additional_options = 'Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr +MACs hmac-sha2-512,hmac-sha2-256,hmac-ripemd160' +  } + +  ## +  ## SSHD SERVER CONFIGURATION +  ## +  class { '::sshd': +    manage_nagios           => false, +    ports                   => [ $ssh['port'] ], +    use_pam                 => 'yes', +    print_motd              => 'no', +    tcp_forwarding          => $ssh_config['AllowTcpForwarding'], +    manage_client           => false, +    use_storedconfigs       => false, +    tail_additional_options => $tail_additional_options, +    hostkey_type            => [ 'rsa', 'dsa', 'ecdsa' ] +  } +} diff --git a/puppet/modules/site_sshd/manifests/mosh.pp b/puppet/modules/site_sshd/manifests/mosh.pp new file mode 100644 index 00000000..49f56ca0 --- /dev/null +++ b/puppet/modules/site_sshd/manifests/mosh.pp @@ -0,0 +1,21 @@ +class site_sshd::mosh ( $ensure = present, $ports = '60000-61000' ) { + +  package { 'mosh': +    ensure => $ensure +  } + +  file { '/etc/shorewall/macro.mosh': +    ensure  => $ensure, +    content => "PARAM   -       -       udp    ${ports}", +    notify  => Service['shorewall'], +    require => Package['shorewall']; +  } + +  shorewall::rule { 'net2fw-mosh': +    ensure      => $ensure, +    source      => 'net', +    destination => '$FW', +    action      => 'mosh(ACCEPT)', +    order       => 200; +  } +} diff --git a/puppet/modules/site_sshd/templates/authorized_keys.erb b/puppet/modules/site_sshd/templates/authorized_keys.erb new file mode 100644 index 00000000..51bdc5b3 --- /dev/null +++ b/puppet/modules/site_sshd/templates/authorized_keys.erb @@ -0,0 +1,10 @@ +# NOTICE: This file is autogenerated by Puppet +# all manually added keys will be overridden + +<% @keys.sort.each do |user, hash| -%> +<% if user == 'monitor' -%> +command="/usr/bin/check_mk_agent",no-port-forwarding,no-x11-forwarding,no-agent-forwarding,no-pty,no-user-rc, <%=hash['type']-%> <%=hash['key']%> <%=user%>  +<% else -%> +<%=hash['type']-%> <%=hash['key']%> <%=user%>  +<% end -%> +<% end -%>  diff --git a/puppet/modules/site_sshd/templates/ssh_config.erb b/puppet/modules/site_sshd/templates/ssh_config.erb new file mode 100644 index 00000000..36c0b6d5 --- /dev/null +++ b/puppet/modules/site_sshd/templates/ssh_config.erb @@ -0,0 +1,40 @@ +# This file is generated by Puppet +# This is the ssh client system-wide configuration file.  See +# ssh_config(5) for more information.  This file provides defaults for +# users, and the values can be changed in per-user configuration files +# or on the command line. + +Host * +    SendEnv LANG LC_* +    HashKnownHosts yes +    GSSAPIAuthentication yes +    GSSAPIDelegateCredentials no +<% if scope.lookupvar('::site_config::params::environment') == 'local' -%> +    # +    # Vagrant nodes should have strict host key checking +    # turned off. The problem is that the host key for a vagrant +    # node is specific to the particular instance of the vagrant +    # node you have running locally. For this reason, we can't +    # track the host keys, or your host key for vpn1 would conflict +    # with my host key for vpn1. +    # +    StrictHostKeyChecking no +<% end -%> + +# +# Tell SSH what host key algorithm we should use. I don't understand why this +# is needed, since the man page says that "if hostkeys are known for the +# destination host then [HostKeyAlgorithms default] is modified to prefer +# their algorithms." +# + +<% @hosts.sort.each do |name, host| -%> +Host <%= name %> <%= host['domain_full'] %> <%= host['domain_internal'] %> <%= host['ip_address'] %> +<% if host['host_pub_key'] -%> +HostKeyAlgorithms <%= host['host_pub_key'].split(" ").first %> +<% end -%> +<% if host['port'] -%> +Port <%= host['port'] %> +<% end -%> + +<% end -%> diff --git a/puppet/modules/site_sshd/templates/ssh_known_hosts.erb b/puppet/modules/site_sshd/templates/ssh_known_hosts.erb new file mode 100644 index 00000000..002ab732 --- /dev/null +++ b/puppet/modules/site_sshd/templates/ssh_known_hosts.erb @@ -0,0 +1,7 @@ +# This file is generated by Puppet + +<% @hosts.sort.each do |name, hash| -%> +<%   if hash['host_pub_key'] -%> +<%=    name%>,<%=hash['domain_full']%>,<%=hash['domain_internal']%>,<%=hash['ip_address']%> <%=hash['host_pub_key']%> +<%   end -%> +<% end -%> diff --git a/puppet/modules/site_static/README b/puppet/modules/site_static/README new file mode 100644 index 00000000..bc719782 --- /dev/null +++ b/puppet/modules/site_static/README @@ -0,0 +1,3 @@ +Deploy one or more static websites to a node. + +For now, it only supports `amber` based static sites. Should support plain html and jekyll in the future. diff --git a/puppet/modules/site_static/manifests/domain.pp b/puppet/modules/site_static/manifests/domain.pp new file mode 100644 index 00000000..b26cc9e3 --- /dev/null +++ b/puppet/modules/site_static/manifests/domain.pp @@ -0,0 +1,33 @@ +# configure static service for domain +define site_static::domain ( +  $ca_cert, +  $key, +  $cert, +  $tls_only=true, +  $locations=undef, +  $aliases=undef, +  $apache_config=undef) { + +  $domain = $name +  $base_dir = '/srv/static' + +  $cafile = "${cert}\n${ca_cert}" + +  if is_hash($locations) { +    create_resources(site_static::location, $locations) +  } + +  x509::cert { $domain: +    content => $cafile, +    notify  => Service[apache] +  } +  x509::key { $domain: +    content => $key, +    notify  => Service[apache] +  } + +  apache::vhost::file { $domain: +    content => template('site_static/apache.conf.erb') +  } + +} diff --git a/puppet/modules/site_static/manifests/init.pp b/puppet/modules/site_static/manifests/init.pp new file mode 100644 index 00000000..4a722d62 --- /dev/null +++ b/puppet/modules/site_static/manifests/init.pp @@ -0,0 +1,72 @@ +# deploy static service +class site_static { +  tag 'leap_service' + +  include site_config::default +  include site_config::x509::cert +  include site_config::x509::key +  include site_config::x509::ca_bundle + +  $static        = hiera('static') +  $domains       = $static['domains'] +  $formats       = $static['formats'] +  $bootstrap     = $static['bootstrap_files'] +  $tor           = hiera('tor', false) + +  if $bootstrap['enabled'] { +    $bootstrap_domain  = $bootstrap['domain'] +    $bootstrap_client  = $bootstrap['client_version'] +    file { '/srv/leap/provider.json': +      content => $bootstrap['provider_json'], +      owner   => 'www-data', +      group   => 'www-data', +      mode    => '0444'; +    } +    # It is important to always touch provider.json: the client needs to check x-min-client-version header, +    # but this is only sent when the file has been modified (otherwise 304 is sent by apache). The problem +    # is that changing min client version won't alter the content of provider.json, so we must touch it. +    exec { '/bin/touch /srv/leap/provider.json': +      require => File['/srv/leap/provider.json']; +    } +  } + +  include apache::module::headers +  include apache::module::alias +  include apache::module::expires +  include apache::module::removeip +  include apache::module::dir +  include apache::module::negotiation +  include site_apache::common +  include site_config::ruby::dev + +  if (member($formats, 'rack')) { +    include site_apt::preferences::passenger +    class { 'passenger': +      use_munin => false, +      require   => Class['site_apt::preferences::passenger'] +    } +  } + +  if (member($formats, 'amber')) { +    rubygems::gem{'amber-0.3.8': +      require =>  Package['zlib1g-dev'] +    } + +    package { 'zlib1g-dev': +        ensure => installed +    } +  } + +  create_resources(site_static::domain, $domains) + +  if $tor { +    $hidden_service = $tor['hidden_service'] +    if $hidden_service['active'] { +      include site_webapp::hidden_service +    } +  } + +  include site_shorewall::defaults +  include site_shorewall::service::http +  include site_shorewall::service::https +} diff --git a/puppet/modules/site_static/manifests/location.pp b/puppet/modules/site_static/manifests/location.pp new file mode 100644 index 00000000..d116de2f --- /dev/null +++ b/puppet/modules/site_static/manifests/location.pp @@ -0,0 +1,36 @@ +# configure static service for location +define site_static::location($path, $format, $source) { + +  $file_path = "/srv/static/${name}" +  $allowed_formats = ['amber','rack'] + +  if $format == undef { +    fail("static_site location `${path}` is missing `format` field.") +  } + +  if ! member($allowed_formats, $format) { +    $formats_str = join($allowed_formats, ', ') +    fail("Unsupported static_site location format `${format}`. Supported formats include ${formats_str}.") +  } + +  if ($format == 'amber') { +    exec {"amber_build_${name}": +      cwd       => $file_path, +      command   => 'amber rebuild', +      user      => 'www-data', +      timeout   => 600, +      subscribe => Vcsrepo[$file_path] +    } +  } + +  vcsrepo { $file_path: +    ensure   => present, +    force    => true, +    revision => $source['revision'], +    provider => $source['type'], +    source   => $source['repo'], +    owner    => 'www-data', +    group    => 'www-data' +  } + +} diff --git a/puppet/modules/site_static/templates/amber.erb b/puppet/modules/site_static/templates/amber.erb new file mode 100644 index 00000000..694f1136 --- /dev/null +++ b/puppet/modules/site_static/templates/amber.erb @@ -0,0 +1,13 @@ +<%- if @location_path != '' -%> +  AliasMatch ^/[a-z]{2}/<%=@location_path%>(/.+|/|)$ "<%=@directory%>/$1" +  Alias /<%=@location_path%> "<%=@directory%>/" +<%- end -%> +  <Directory "<%=@directory%>/"> +    AllowOverride FileInfo Indexes Options=All,MultiViews +<% if scope.function_guess_apache_version([]) == '2.4' %> +    Require all granted +<% else %> +    Order deny,allow +    Allow from all +<% end %> +  </Directory> diff --git a/puppet/modules/site_static/templates/apache.conf.erb b/puppet/modules/site_static/templates/apache.conf.erb new file mode 100644 index 00000000..6b969d1c --- /dev/null +++ b/puppet/modules/site_static/templates/apache.conf.erb @@ -0,0 +1,88 @@ +<%- +  ## +  ## An apache config for static websites. +  ## + +  def location_directory(name, location) +    if ['amber', 'rack'].include?(location['format']) +      File.join(@base_dir, name, 'public') +    else +      File.join(@base_dir, name) +    end +  end + +  @document_root = begin +    root = '/var/www' +    @locations && @locations.each do |name, location| +      root = location_directory(name, location) if location['path'] == '/' +    end +    root.gsub(%r{^/|/$}, '') +  end + +  bootstrap_domain = scope.lookupvar('site_static::bootstrap_domain') +  bootstrap_client = scope.lookupvar('site_static::bootstrap_client') +-%> + +<VirtualHost *:80> +  ServerName <%= @domain %> +  ServerAlias www.<%= @domain %> +<%- @aliases && @aliases.each do |domain_alias| -%> +  ServerAlias <%= domain_alias %> +<%- end -%> +<%- if @tls_only -%> +  RewriteEngine On +  RewriteRule ^.*$ https://<%= @domain -%>%{REQUEST_URI} [R=permanent,L] +<%- end -%> +</VirtualHost> + +<VirtualHost *:443> +  ServerName <%= @domain %> +  ServerAlias www.<%= @domain %> +<%- @aliases && @aliases.each do |domain_alias| -%> +  ServerAlias <%= domain_alias %> +<%- end -%> + +  #RewriteLog "/var/log/apache2/rewrite.log" +  #RewriteLogLevel 3 + +  Include include.d/ssl_common.inc +   +<%- if @tls_only -%> +  Header always set Strict-Transport-Security: "max-age=15768000;includeSubdomains" +<%- end -%> +  Header set X-Frame-Options "deny" +  Header always unset X-Powered-By +  Header always unset X-Runtime + +  SSLCertificateKeyFile    /etc/x509/keys/<%= @domain %>.key +  SSLCertificateFile       /etc/x509/certs/<%= @domain %>.crt + +  RequestHeader set X_FORWARDED_PROTO 'https' + +  DocumentRoot "/<%= @document_root %>/" +  AccessFileName .htaccess + +<%- if ([@aliases]+[@domain]).flatten.include?(bootstrap_domain) -%> +  Alias /provider.json /srv/leap/provider.json +  <Location /provider.json> +    Header set X-Minimum-Client-Version <%= bootstrap_client['min'] %> +  </Location> +<%- end -%> + +<%- if @apache_config -%> +<%=   @apache_config.gsub(':percent:','%') %> +<%- end -%> + +<%- @locations && @locations.each do |name, location| -%> +<%-   location_path = location['path'].gsub(%r{^/|/$}, '') -%> +<%-   directory = location_directory(name, location) -%> +<%-   local_vars = {'location_path'=>location_path, 'directory'=>directory, 'location'=>location, 'name'=>name} -%> +<%-   template_path = File.join(File.dirname(__FILE__), location['format']) + '.erb' -%> +<%-   break unless File.exists?(template_path) -%> +  ## +  ## <%= name %> (<%= location['format'] %>) +  ## +<%=   scope.function_templatewlv([template_path, local_vars]) %> +<%- end -%> + +</VirtualHost> diff --git a/puppet/modules/site_static/templates/rack.erb b/puppet/modules/site_static/templates/rack.erb new file mode 100644 index 00000000..431778bb --- /dev/null +++ b/puppet/modules/site_static/templates/rack.erb @@ -0,0 +1,19 @@ +  #PassengerLogLevel 1 +  #PassengerAppEnv production +  #PassengerFriendlyErrorPages on +<%- if @location_path != '' -%> +  Alias /<%=@location_path%> "<%=@directory%>" +  <Location /<%=@location_path%>> +    PassengerBaseURI /<%=@location_path%> +    PassengerAppRoot "<%=File.dirname(@directory)%>" +  </Location> +<%- end -%> +  <Directory "<%=@directory%>"> +    Options -MultiViews +<% if scope.function_guess_apache_version([]) == '2.4' %> +    Require all granted +<% else %> +    Order deny,allow +    Allow from all +<% end %> +  </Directory> diff --git a/puppet/modules/site_stunnel/manifests/client.pp b/puppet/modules/site_stunnel/manifests/client.pp new file mode 100644 index 00000000..c9e034f1 --- /dev/null +++ b/puppet/modules/site_stunnel/manifests/client.pp @@ -0,0 +1,64 @@ +# +# Sets up stunnel and firewall configuration for +# a single stunnel client +# +# As a client, we accept connections on localhost, +# and connect to a remote $connect:$connect_port +# + +define site_stunnel::client ( +  $accept_port, +  $connect_port, +  $connect, +  $original_port, +  $verify     = '2', +  $pid        = $name, +  $rndfile    = '/var/lib/stunnel4/.rnd', +  $debuglevel = 'warning' ) { + +  $logfile = "/var/log/stunnel4/${name}.log" + +  include site_config::x509::cert +  include site_config::x509::key +  include site_config::x509::ca +  include x509::variables +  $ca_path   = "${x509::variables::local_CAs}/${site_config::params::ca_name}.crt" +  $cert_path = "${x509::variables::certs}/${site_config::params::cert_name}.crt" +  $key_path  = "${x509::variables::keys}/${site_config::params::cert_name}.key" + +  stunnel::service { $name: +    accept     => "127.0.0.1:${accept_port}", +    connect    => "${connect}:${connect_port}", +    client     => true, +    cafile     => $ca_path, +    key        => $key_path, +    cert       => $cert_path, +    verify     => $verify, +    pid        => "/var/run/stunnel4/${pid}.pid", +    rndfile    => $rndfile, +    debuglevel => $debuglevel, +    sslversion => 'TLSv1', +    syslog     => 'no', +    output     => $logfile; +  } + +  # define the log files so that we can purge the +  # files from /var/log/stunnel4 that are not defined. +  file { +    $logfile:; +    "${logfile}.1.gz":; +    "${logfile}.2.gz":; +    "${logfile}.3.gz":; +    "${logfile}.4.gz":; +    "${logfile}.5.gz":; +  } + +  site_shorewall::stunnel::client { $name: +    accept_port   => $accept_port, +    connect       => $connect, +    connect_port  => $connect_port, +    original_port => $original_port +  } + +  include site_check_mk::agent::stunnel +} diff --git a/puppet/modules/site_stunnel/manifests/clients.pp b/puppet/modules/site_stunnel/manifests/clients.pp new file mode 100644 index 00000000..c0958b5f --- /dev/null +++ b/puppet/modules/site_stunnel/manifests/clients.pp @@ -0,0 +1,23 @@ +# +# example hiera yaml: +# +#   stunnel: +#     clients: +#       ednp_clients: +#         thrips_9002: +#           accept_port: 4001 +#           connect: thrips.demo.bitmask.i +#           connect_port: 19002 +#       epmd_clients: +#         thrips_4369: +#           accept_port: 4000 +#           connect: thrips.demo.bitmask.i +#           connect_port: 14369 +# +# In the above example, this resource definition is called twice, with $name +# 'ednp_clients' and 'epmd_clients' +# + +define site_stunnel::clients { +  create_resources(site_stunnel::client, $site_stunnel::clients[$name]) +} diff --git a/puppet/modules/site_stunnel/manifests/init.pp b/puppet/modules/site_stunnel/manifests/init.pp new file mode 100644 index 00000000..a874721f --- /dev/null +++ b/puppet/modules/site_stunnel/manifests/init.pp @@ -0,0 +1,48 @@ +# +# If you need something to happen after stunnel is started, +# you can depend on Service['stunnel'] or Class['site_stunnel'] +# + +class site_stunnel { + +  # include the generic stunnel module +  # increase the number of open files to allow for 800 connections +  class { 'stunnel': default_extra => 'ulimit -n 4096' } + +  # The stunnel.conf provided by the Debian package is broken by default +  # so we get rid of it and just define our own. See #549384 +  if !defined(File['/etc/stunnel/stunnel.conf']) { +    file { +      # this file is a broken config installed by the package +      '/etc/stunnel/stunnel.conf': +        ensure => absent; +    } +  } + +  $stunnel = hiera('stunnel') + +  # add server stunnels +  create_resources(site_stunnel::servers, $stunnel['servers']) + +  # add client stunnels +  $clients = $stunnel['clients'] +  $client_sections = keys($clients) +  site_stunnel::clients { $client_sections: } + +  # remove any old stunnel logs that are not +  # defined by this puppet run +  file {'/var/log/stunnel4': purge => true;} + +  # the default is to keep 356 log files for each stunnel. +  # here we set a more reasonable number. +  augeas { +    'logrotate_stunnel': +      context => '/files/etc/logrotate.d/stunnel4/rule', +      changes => [ +        'set rotate 5', +      ] +  } + +  include site_stunnel::override_service +} + diff --git a/puppet/modules/site_stunnel/manifests/override_service.pp b/puppet/modules/site_stunnel/manifests/override_service.pp new file mode 100644 index 00000000..435b9aa0 --- /dev/null +++ b/puppet/modules/site_stunnel/manifests/override_service.pp @@ -0,0 +1,18 @@ +# override stunnel::debian defaults +# +# ignore puppet lint error about inheriting from different namespace +# lint:ignore:inherits_across_namespaces +class site_stunnel::override_service inherits stunnel::debian { +# lint:endignore + +  include site_config::x509::cert +  include site_config::x509::key +  include site_config::x509::ca + +  Service[stunnel] { +    subscribe => [ +                  Class['Site_config::X509::Key'], +                  Class['Site_config::X509::Cert'], +                  Class['Site_config::X509::Ca'] ] +  } +} diff --git a/puppet/modules/site_stunnel/manifests/servers.pp b/puppet/modules/site_stunnel/manifests/servers.pp new file mode 100644 index 00000000..e76d1e9d --- /dev/null +++ b/puppet/modules/site_stunnel/manifests/servers.pp @@ -0,0 +1,51 @@ +# +# example hiera yaml: +# +#   stunnel: +#     servers: +#       couch_server: +#         accept_port: 15984 +#         connect_port: 5984 +# + +define site_stunnel::servers ( +  $accept_port, +  $connect_port, +  $verify     = '2', +  $pid        = $name, +  $rndfile    = '/var/lib/stunnel4/.rnd', +  $debuglevel = '4' ) { + +  $logfile = "/var/log/stunnel4/${name}.log" + +  include site_config::x509::cert +  include site_config::x509::key +  include site_config::x509::ca +  include x509::variables +  $ca_path   = "${x509::variables::local_CAs}/${site_config::params::ca_name}.crt" +  $cert_path = "${x509::variables::certs}/${site_config::params::cert_name}.crt" +  $key_path  = "${x509::variables::keys}/${site_config::params::cert_name}.key" + +  stunnel::service { $name: +    accept     => $accept_port, +    connect    => "127.0.0.1:${connect_port}", +    client     => false, +    cafile     => $ca_path, +    key        => $key_path, +    cert       => $cert_path, +    verify     => $verify, +    pid        => "/var/run/stunnel4/${pid}.pid", +    rndfile    => '/var/lib/stunnel4/.rnd', +    debuglevel => $debuglevel, +    sslversion => 'TLSv1', +    syslog     => 'no', +    output     => $logfile; +  } + +  # allow incoming connections on $accept_port +  site_shorewall::stunnel::server { $name: +    port  => $accept_port +  } + +  include site_check_mk::agent::stunnel +} diff --git a/puppet/modules/site_tor/manifests/disable_exit.pp b/puppet/modules/site_tor/manifests/disable_exit.pp new file mode 100644 index 00000000..078f80ae --- /dev/null +++ b/puppet/modules/site_tor/manifests/disable_exit.pp @@ -0,0 +1,7 @@ +class site_tor::disable_exit { +  tor::daemon::exit_policy { +    'no_exit_at_all': +      reject => [ '*:*' ]; +  } +} + diff --git a/puppet/modules/site_tor/manifests/init.pp b/puppet/modules/site_tor/manifests/init.pp new file mode 100644 index 00000000..2207a5a9 --- /dev/null +++ b/puppet/modules/site_tor/manifests/init.pp @@ -0,0 +1,45 @@ +class site_tor { +  tag 'leap_service' +  Class['site_config::default'] -> Class['site_tor'] + +  $tor            = hiera('tor') +  $bandwidth_rate = $tor['bandwidth_rate'] +  $tor_type       = $tor['type'] +  $nickname       = $tor['nickname'] +  $contact_emails = join($tor['contacts'],', ') +  $family         = $tor['family'] + +  $address        = hiera('ip_address') + +  $openvpn        = hiera('openvpn', undef) +  if $openvpn { +    $openvpn_ports = $openvpn['ports'] +  } +  else { +    $openvpn_ports = [] +  } + +  include site_config::default +  include tor::daemon +  tor::daemon::relay { $nickname: +    port           => 9001, +    address        => $address, +    contact_info   => obfuscate_email($contact_emails), +    bandwidth_rate => $bandwidth_rate, +    my_family      => $family +  } + +  if ( $tor_type == 'exit'){ +    # Only enable the daemon directory if the node isn't also a webapp node +    # or running openvpn on port 80 +    if ! member($::services, 'webapp') and ! member($openvpn_ports, '80') { +      tor::daemon::directory { $::hostname: port => 80 } +    } +  } +  else { +    include site_tor::disable_exit +  } + +  include site_shorewall::tor + +} diff --git a/puppet/modules/site_webapp/files/server-status.conf b/puppet/modules/site_webapp/files/server-status.conf new file mode 100644 index 00000000..10b2d4ed --- /dev/null +++ b/puppet/modules/site_webapp/files/server-status.conf @@ -0,0 +1,26 @@ +# Keep track of extended status information for each request +ExtendedStatus On + +# Determine if mod_status displays the first 63 characters of a request or +# the last 63, assuming the request itself is greater than 63 chars. +# Default: Off +#SeeRequestTail On + +Listen 127.0.0.1:8162 + +<VirtualHost 127.0.0.1:8162> + +<Location /server-status> +    SetHandler server-status +    Require all granted +    Allow from 127.0.0.1 +</Location> + +</VirtualHost> + + +<IfModule mod_proxy.c> +    # Show Proxy LoadBalancer status in mod_status +    ProxyStatus On +</IfModule> + diff --git a/puppet/modules/site_webapp/manifests/apache.pp b/puppet/modules/site_webapp/manifests/apache.pp new file mode 100644 index 00000000..80c7b29b --- /dev/null +++ b/puppet/modules/site_webapp/manifests/apache.pp @@ -0,0 +1,28 @@ +# configure apache and passenger to serve the webapp +class site_webapp::apache { + +  $web_api          = hiera('api') +  $api_domain       = $web_api['domain'] +  $api_port         = $web_api['port'] + +  $web_domain       = hiera('domain') +  $domain_name      = $web_domain['name'] + +  $webapp           = hiera('webapp') +  $webapp_domain    = $webapp['domain'] + +  include site_apache::common +  include apache::module::headers +  include apache::module::alias +  include apache::module::expires +  include apache::module::removeip +  include site_webapp::common_vhost + +  class { 'passenger': use_munin => false } + +  apache::vhost::file { +    'api': +      content => template('site_apache/vhosts.d/api.conf.erb'); +  } + +} diff --git a/puppet/modules/site_webapp/manifests/common_vhost.pp b/puppet/modules/site_webapp/manifests/common_vhost.pp new file mode 100644 index 00000000..c57aad57 --- /dev/null +++ b/puppet/modules/site_webapp/manifests/common_vhost.pp @@ -0,0 +1,18 @@ +class site_webapp::common_vhost { +  # installs x509 cert + key and common config +  # that both nagios + leap webapp use + +  include x509::variables +  include site_config::x509::commercial::cert +  include site_config::x509::commercial::key +  include site_config::x509::commercial::ca + +  Class['Site_config::X509::Commercial::Key'] ~> Service[apache] +  Class['Site_config::X509::Commercial::Cert'] ~> Service[apache] +  Class['Site_config::X509::Commercial::Ca'] ~> Service[apache] + +  apache::vhost::file { +  'common': +    content => template('site_apache/vhosts.d/common.conf.erb') +  } +} diff --git a/puppet/modules/site_webapp/manifests/couchdb.pp b/puppet/modules/site_webapp/manifests/couchdb.pp new file mode 100644 index 00000000..71450370 --- /dev/null +++ b/puppet/modules/site_webapp/manifests/couchdb.pp @@ -0,0 +1,52 @@ +class site_webapp::couchdb { + +  $webapp                  = hiera('webapp') +  # haproxy listener on port localhost:4096, see site_webapp::haproxy +  $couchdb_host            = 'localhost' +  $couchdb_port            = '4096' +  $couchdb_webapp_user     = $webapp['couchdb_webapp_user']['username'] +  $couchdb_webapp_password = $webapp['couchdb_webapp_user']['password'] +  $couchdb_admin_user      = $webapp['couchdb_admin_user']['username'] +  $couchdb_admin_password  = $webapp['couchdb_admin_user']['password'] + +  include x509::variables + +  file { +    '/srv/leap/webapp/config/couchdb.yml': +      content => template('site_webapp/couchdb.yml.erb'), +      owner   => 'leap-webapp', +      group   => 'leap-webapp', +      mode    => '0600', +      require => Vcsrepo['/srv/leap/webapp']; + +    # couchdb.admin.yml is a symlink to prevent the vcsrepo resource +    # from changing its user permissions every time. +    '/srv/leap/webapp/config/couchdb.admin.yml': +      ensure => 'link', +      target => '/etc/leap/couchdb.admin.yml', +      require => Vcsrepo['/srv/leap/webapp']; + +    '/etc/leap/couchdb.admin.yml': +      content => template('site_webapp/couchdb.admin.yml.erb'), +      owner   => 'root', +      group   => 'root', +      mode    => '0600', +      require => File['/etc/leap']; + +    '/srv/leap/webapp/log': +      ensure  => directory, +      owner   => 'leap-webapp', +      group   => 'leap-webapp', +      mode    => '0755', +      require => Vcsrepo['/srv/leap/webapp']; + +    '/srv/leap/webapp/log/production.log': +      ensure  => present, +      owner   => 'leap-webapp', +      group   => 'leap-webapp', +      mode    => '0666', +      require => Vcsrepo['/srv/leap/webapp']; +  } + +  include site_stunnel +} diff --git a/puppet/modules/site_webapp/manifests/cron.pp b/puppet/modules/site_webapp/manifests/cron.pp new file mode 100644 index 00000000..70b9da04 --- /dev/null +++ b/puppet/modules/site_webapp/manifests/cron.pp @@ -0,0 +1,37 @@ +# setup webapp cronjobs +class site_webapp::cron { + +  # cron tasks that need to be performed to cleanup the database +  cron { +    'rotate_databases': +      command     => 'cd /srv/leap/webapp && bundle exec rake db:rotate', +      environment => 'RAILS_ENV=production', +      user        => 'root', +      hour        => [0,6,12,18], +      minute      => 0; + +    'delete_tmp_databases': +      command     => 'cd /srv/leap/webapp && bundle exec rake db:deletetmp', +      environment => 'RAILS_ENV=production', +      user        => 'root', +      hour        => 1, +      minute      => 1; + +    # there is no longer a need to remove expired sessions, since the database +    # will get destroyed. +    'remove_expired_sessions': +      ensure      => absent, +      command     => 'cd /srv/leap/webapp && bundle exec rake cleanup:sessions', +      environment => 'RAILS_ENV=production', +      user        => 'leap-webapp', +      hour        => 2, +      minute      => 30; + +    'remove_expired_tokens': +      command     => 'cd /srv/leap/webapp && bundle exec rake cleanup:tokens', +      environment => 'RAILS_ENV=production', +      user        => 'leap-webapp', +      hour        => 3, +      minute      => 0; +  } +} diff --git a/puppet/modules/site_webapp/manifests/hidden_service.pp b/puppet/modules/site_webapp/manifests/hidden_service.pp new file mode 100644 index 00000000..72a2ce95 --- /dev/null +++ b/puppet/modules/site_webapp/manifests/hidden_service.pp @@ -0,0 +1,52 @@ +class site_webapp::hidden_service { +  $tor              = hiera('tor') +  $hidden_service   = $tor['hidden_service'] +  $tor_domain       = "${hidden_service['address']}.onion" + +  include site_apache::common +  include apache::module::headers +  include apache::module::alias +  include apache::module::expires +  include apache::module::removeip +   +  include tor::daemon +  tor::daemon::hidden_service { 'webapp': ports => [ '80 127.0.0.1:80'] } + +  file { +    '/var/lib/tor/webapp/': +      ensure  => directory, +      owner   => 'debian-tor', +      group   => 'debian-tor', +      mode    => '2700'; + +    '/var/lib/tor/webapp/private_key': +      ensure  => present, +      source  => "/srv/leap/files/nodes/${::hostname}/tor.key", +      owner   => 'debian-tor', +      group   => 'debian-tor', +      mode    => '0600'; + +    '/var/lib/tor/webapp/hostname': +      ensure  => present, +      content => $tor_domain, +      owner   => 'debian-tor', +      group   => 'debian-tor', +      mode    => '0600'; +  } + +  # it is necessary to zero out the config of the status module +  # because we are configuring our own version that is unavailable +  # over the hidden service (see: #7456 and #7776) +  apache::module { 'status': ensure => present, conf_content => ' ' } +  # the access_compat module is required to enable Allow directives +  apache::module { 'access_compat': ensure => present } +   +  apache::vhost::file { +    'hidden_service': +      content => template('site_apache/vhosts.d/hidden_service.conf.erb'); +    'server_status': +      vhost_source => 'modules/site_webapp/server-status.conf'; +  } + +  include site_shorewall::tor +} diff --git a/puppet/modules/site_webapp/manifests/init.pp b/puppet/modules/site_webapp/manifests/init.pp new file mode 100644 index 00000000..15925aba --- /dev/null +++ b/puppet/modules/site_webapp/manifests/init.pp @@ -0,0 +1,179 @@ +# configure webapp service +class site_webapp { +  tag 'leap_service' +  $definition_files = hiera('definition_files') +  $provider         = $definition_files['provider'] +  $eip_service      = $definition_files['eip_service'] +  $soledad_service  = $definition_files['soledad_service'] +  $smtp_service     = $definition_files['smtp_service'] +  $node_domain      = hiera('domain') +  $provider_domain  = $node_domain['full_suffix'] +  $webapp           = hiera('webapp') +  $api_version      = $webapp['api_version'] +  $secret_token     = $webapp['secret_token'] +  $tor              = hiera('tor', false) +  $sources          = hiera('sources') + +  Class['site_config::default'] -> Class['site_webapp'] + +  include site_config::ruby::dev +  include site_webapp::apache +  include site_webapp::couchdb +  include site_haproxy +  include site_webapp::cron +  include site_config::default +  include site_config::x509::cert +  include site_config::x509::key +  include site_config::x509::ca +  include site_config::x509::client_ca::ca +  include site_config::x509::client_ca::key +  include site_nickserver + +  # remove leftovers from previous installations on webapp nodes +  include site_config::remove::webapp + +  group { 'leap-webapp': +    ensure    => present, +    allowdupe => false; +  } + +  user { 'leap-webapp': +    ensure    => present, +    allowdupe => false, +    gid       => 'leap-webapp', +    groups    => 'ssl-cert', +    home      => '/srv/leap/webapp', +    require   => [ Group['leap-webapp'] ]; +  } + +  vcsrepo { '/srv/leap/webapp': +    ensure   => present, +    force    => true, +    revision => $sources['webapp']['revision'], +    provider => $sources['webapp']['type'], +    source   => $sources['webapp']['source'], +    owner    => 'leap-webapp', +    group    => 'leap-webapp', +    require  => [ User['leap-webapp'], Group['leap-webapp'] ], +    notify   => Exec['bundler_update'] +  } + +  exec { 'bundler_update': +    cwd     => '/srv/leap/webapp', +    command => '/bin/bash -c "/usr/bin/bundle check --path vendor/bundle || /usr/bin/bundle install --path vendor/bundle --without test development debug"', +    unless  => '/usr/bin/bundle check --path vendor/bundle', +    user    => 'leap-webapp', +    timeout => 600, +    require => [ +      Class['bundler::install'], +      Vcsrepo['/srv/leap/webapp'], +      Class['site_config::ruby::dev'], +      Service['shorewall'] ], +    notify  => Service['apache']; +  } + +  # +  # NOTE: in order to support a webapp that is running on a subpath and not the +  # root of the domain assets:precompile needs to be run with +  # RAILS_RELATIVE_URL_ROOT=/application-root +  # + +  exec { 'compile_assets': +    cwd       => '/srv/leap/webapp', +    command   => '/bin/bash -c "RAILS_ENV=production /usr/bin/bundle exec rake assets:precompile"', +    user      => 'leap-webapp', +    logoutput => on_failure, +    require   => Exec['bundler_update'], +    notify    => Service['apache']; +  } + +  file { +    '/srv/leap/webapp/config/provider': +      ensure  => directory, +      require => Vcsrepo['/srv/leap/webapp'], +      owner   => leap-webapp, group => leap-webapp, mode => '0755'; + +    '/srv/leap/webapp/config/provider/provider.json': +      content => $provider, +      require => Vcsrepo['/srv/leap/webapp'], +      owner   => leap-webapp, group => leap-webapp, mode => '0644'; + +    '/srv/leap/webapp/public/ca.crt': +      ensure  => link, +      require => Vcsrepo['/srv/leap/webapp'], +      target  => "${x509::variables::local_CAs}/${site_config::params::ca_name}.crt"; + +    "/srv/leap/webapp/public/${api_version}": +      ensure  => directory, +      require => Vcsrepo['/srv/leap/webapp'], +      owner   => leap-webapp, group => leap-webapp, mode => '0755'; + +    "/srv/leap/webapp/public/${api_version}/config/": +      ensure  => directory, +      require => Vcsrepo['/srv/leap/webapp'], +      owner   => leap-webapp, group => leap-webapp, mode => '0755'; + +    "/srv/leap/webapp/public/${api_version}/config/eip-service.json": +      content => $eip_service, +      require => Vcsrepo['/srv/leap/webapp'], +      owner   => leap-webapp, group => leap-webapp, mode => '0644'; + +    "/srv/leap/webapp/public/${api_version}/config/soledad-service.json": +      content => $soledad_service, +      require => Vcsrepo['/srv/leap/webapp'], +      owner   => leap-webapp, group => leap-webapp, mode => '0644'; + +    "/srv/leap/webapp/public/${api_version}/config/smtp-service.json": +      content => $smtp_service, +      require => Vcsrepo['/srv/leap/webapp'], +      owner   => leap-webapp, group => leap-webapp, mode => '0644'; +  } + +  try::file { +    '/srv/leap/webapp/config/customization': +      ensure  => directory, +      recurse => true, +      purge   => true, +      force   => true, +      owner   => leap-webapp, +      group   => leap-webapp, +      mode    => 'u=rwX,go=rX', +      require => Vcsrepo['/srv/leap/webapp'], +      notify  => Exec['compile_assets'], +      source  => $webapp['customization_dir']; +  } + +  git::changes { +    'public/favicon.ico': +      cwd     => '/srv/leap/webapp', +      require => Vcsrepo['/srv/leap/webapp'], +      user    => 'leap-webapp'; +  } + +  file { +    '/srv/leap/webapp/config/config.yml': +      content => template('site_webapp/config.yml.erb'), +      owner   => leap-webapp, +      group   => leap-webapp, +      mode    => '0600', +      require => Vcsrepo['/srv/leap/webapp'], +      notify  => Service['apache']; +  } + +  if $tor { +    $hidden_service = $tor['hidden_service'] +    if $hidden_service['active'] { +      include site_webapp::hidden_service +    } +  } + + +  # needed for the soledad-sync check which is run on the +  # webapp node +  include soledad::client + +  leap::logfile { 'webapp': } + +  include site_shorewall::webapp +  include site_check_mk::agent::webapp +} diff --git a/puppet/modules/site_webapp/templates/config.yml.erb b/puppet/modules/site_webapp/templates/config.yml.erb new file mode 100644 index 00000000..dd55d3e9 --- /dev/null +++ b/puppet/modules/site_webapp/templates/config.yml.erb @@ -0,0 +1,36 @@ +<% +cert_options = @webapp['client_certificates'] +production = { +  "admins" => @webapp['admins'], +  "default_locale" => @webapp['default_locale'], +  "available_locales" => @webapp['locales'], +  "domain" => @provider_domain, +  "force_ssl" => @webapp['secure'], +  "client_ca_key" => "%s/%s.key" % [scope.lookupvar('x509::variables::keys'), scope.lookupvar('site_config::params::client_ca_name')], +  "client_ca_cert" => "%s/%s.crt" % [scope.lookupvar('x509::variables::local_CAs'), scope.lookupvar('site_config::params::client_ca_name')], +  "secret_token" => @secret_token, +  "client_cert_lifespan" => cert_options['life_span'], +  "client_cert_bit_size" => cert_options['bit_size'].to_i, +  "client_cert_hash" => cert_options['digest'], +  "allow_limited_certs" => @webapp['allow_limited_certs'], +  "allow_unlimited_certs" => @webapp['allow_unlimited_certs'], +  "allow_anonymous_certs" => @webapp['allow_anonymous_certs'], +  "limited_cert_prefix" => cert_options['limited_prefix'], +  "unlimited_cert_prefix" => cert_options['unlimited_prefix'], +  "minimum_client_version" => @webapp['client_version']['min'], +  "default_service_level" => @webapp['default_service_level'], +  "service_levels" => @webapp['service_levels'], +  "allow_registration" => @webapp['allow_registration'], +  "handle_blacklist" => @webapp['forbidden_usernames'], +  "invite_required" => @webapp['invite_required'], +  "api_tokens" => @webapp['api_tokens'] +} + +if @webapp['engines'] && @webapp['engines'].any? +  production["engines"] = @webapp['engines'] +end +-%> +# +# This file is generated by puppet. This file inherits from defaults.yml. +# +<%= scope.function_sorted_yaml([{"production" => production}]) %> diff --git a/puppet/modules/site_webapp/templates/couchdb.admin.yml.erb b/puppet/modules/site_webapp/templates/couchdb.admin.yml.erb new file mode 100644 index 00000000..a0921add --- /dev/null +++ b/puppet/modules/site_webapp/templates/couchdb.admin.yml.erb @@ -0,0 +1,9 @@ +production: +  prefix: "" +  protocol: 'http' +  host: <%= @couchdb_host %> +  port: <%= @couchdb_port %> +  auto_update_design_doc: false +  username: <%= @couchdb_admin_user %> +  password: <%= @couchdb_admin_password %> + diff --git a/puppet/modules/site_webapp/templates/couchdb.yml.erb b/puppet/modules/site_webapp/templates/couchdb.yml.erb new file mode 100644 index 00000000..2bef0af5 --- /dev/null +++ b/puppet/modules/site_webapp/templates/couchdb.yml.erb @@ -0,0 +1,9 @@ +production: +  prefix: "" +  protocol: 'http' +  host: <%= @couchdb_host %> +  port: <%= @couchdb_port %> +  auto_update_design_doc: false +  username: <%= @couchdb_webapp_user %> +  password: <%= @couchdb_webapp_password %> + diff --git a/puppet/modules/soledad/manifests/client.pp b/puppet/modules/soledad/manifests/client.pp new file mode 100644 index 00000000..e470adeb --- /dev/null +++ b/puppet/modules/soledad/manifests/client.pp @@ -0,0 +1,16 @@ +# setup soledad-client +# currently needed on webapp node to run the soledad-sync test +class soledad::client { + +  tag 'leap_service' +  include soledad::common + +  package { +    'soledad-client': +      ensure  => latest, +      require => Class['site_apt::leap_repo']; +    'python-u1db': +      ensure => latest; +  } + +} diff --git a/puppet/modules/soledad/manifests/common.pp b/puppet/modules/soledad/manifests/common.pp new file mode 100644 index 00000000..8d8339d4 --- /dev/null +++ b/puppet/modules/soledad/manifests/common.pp @@ -0,0 +1,8 @@ +# install soledad-common, both needed both soledad-client and soledad-server +class soledad::common { + +  package { 'soledad-common': +    ensure  => latest; +  } + +} diff --git a/puppet/modules/soledad/manifests/server.pp b/puppet/modules/soledad/manifests/server.pp new file mode 100644 index 00000000..8674f421 --- /dev/null +++ b/puppet/modules/soledad/manifests/server.pp @@ -0,0 +1,104 @@ +# setup soledad-server +class soledad::server { +  tag 'leap_service' + +  include site_config::default +  include soledad::common + +  $soledad              = hiera('soledad') +  $couchdb_user         = $soledad['couchdb_soledad_user']['username'] +  $couchdb_password     = $soledad['couchdb_soledad_user']['password'] +  $couchdb_leap_mx_user = $soledad['couchdb_leap_mx_user']['username'] + +  $couchdb_host = 'localhost' +  $couchdb_port = '5984' + +  $soledad_port = $soledad['port'] + +  $sources      = hiera('sources') + +  include site_config::x509::cert +  include site_config::x509::key +  include site_config::x509::ca + +  # +  # SOLEDAD CONFIG +  # + +  file { +    '/etc/soledad': +      ensure => directory, +      owner  => 'root', +      group  => 'root', +      mode   => '0755'; +    '/etc/soledad/soledad-server.conf': +      content => template('soledad/soledad-server.conf.erb'), +      owner   => 'soledad', +      group   => 'soledad', +      mode    => '0640', +      notify  => Service['soledad-server'], +      require => [ User['soledad'], Group['soledad'] ]; +    '/srv/leap/soledad': +      ensure  => directory, +      owner   => 'soledad', +      group   => 'soledad', +      require => [ User['soledad'], Group['soledad'] ]; +    '/var/lib/soledad': +      ensure  => directory, +      owner   => 'soledad', +      group   => 'soledad', +      require => [ User['soledad'], Group['soledad'] ]; +  } + +  package { $sources['soledad']['package']: +    ensure  => $sources['soledad']['revision'], +    require => Class['site_apt::leap_repo']; +  } + +  file { '/etc/default/soledad': +    content => template('soledad/default-soledad.erb'), +    owner   => 'soledad', +    group   => 'soledad', +    mode    => '0600', +    notify  => Service['soledad-server'], +    require => [ User['soledad'], Group['soledad'] ]; +  } + +  service { 'soledad-server': +    ensure     => running, +    enable     => true, +    hasstatus  => true, +    hasrestart => true, +    require    => [ User['soledad'], Group['soledad'] ], +    subscribe  => [ +      Package['soledad-server'], +      Class['Site_config::X509::Key'], +      Class['Site_config::X509::Cert'], +      Class['Site_config::X509::Ca'] ]; +  } + +  include site_shorewall::soledad +  include site_check_mk::agent::soledad + +  # set up users, group and directories for soledad-server +  # although the soledad users are already created by the +  # soledad-server package +  group { 'soledad': +    ensure => present, +    system => true, +  } +  user { +    'soledad': +      ensure    => present, +      system    => true, +      gid       => 'soledad', +      home      => '/srv/leap/soledad', +      require   => Group['soledad']; +    'soledad-admin': +      ensure  => present, +      system  => true, +      gid     => 'soledad', +      home    => '/srv/leap/soledad', +      require => Group['soledad']; +  } +} diff --git a/puppet/modules/soledad/templates/default-soledad.erb b/puppet/modules/soledad/templates/default-soledad.erb new file mode 100644 index 00000000..32504e38 --- /dev/null +++ b/puppet/modules/soledad/templates/default-soledad.erb @@ -0,0 +1,5 @@ +# this file is managed by puppet +START=yes +CERT_PATH=<%= scope.lookupvar('x509::variables::certs') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.crt +PRIVKEY_PATH=<%= scope.lookupvar('x509::variables::keys') %>/<%= scope.lookupvar('site_config::params::cert_name') %>.key +HTTPS_PORT=<%=@soledad_port%> diff --git a/puppet/modules/soledad/templates/soledad-server.conf.erb b/puppet/modules/soledad/templates/soledad-server.conf.erb new file mode 100644 index 00000000..1c6a0d19 --- /dev/null +++ b/puppet/modules/soledad/templates/soledad-server.conf.erb @@ -0,0 +1,12 @@ +[soledad-server] +couch_url   = http://<%= @couchdb_user %>:<%= @couchdb_password %>@<%= @couchdb_host %>:<%= @couchdb_port %> +create_cmd  = sudo -u soledad-admin /usr/bin/create-user-db +admin_netrc = /etc/couchdb/couchdb-soledad-admin.netrc + +[database-security] +members = <%= @couchdb_user %>, <%= @couchdb_leap_mx_user %> +# not needed, but for documentation: +# members_roles = replication +# admins = admin +# admins_roles = replication + diff --git a/puppet/modules/sshd/.fixtures.yml b/puppet/modules/sshd/.fixtures.yml new file mode 100644 index 00000000..42598a65 --- /dev/null +++ b/puppet/modules/sshd/.fixtures.yml @@ -0,0 +1,3 @@ +fixtures: +  symlinks: +    sshd: "#{source_dir}"
\ No newline at end of file diff --git a/puppet/modules/sshd/.gitignore b/puppet/modules/sshd/.gitignore new file mode 100644 index 00000000..5ebb01fb --- /dev/null +++ b/puppet/modules/sshd/.gitignore @@ -0,0 +1,4 @@ +.librarian/* +.tmp/* +*.log +spec/fixtures/* diff --git a/puppet/modules/sshd/.rspec b/puppet/modules/sshd/.rspec new file mode 100644 index 00000000..f07c903a --- /dev/null +++ b/puppet/modules/sshd/.rspec @@ -0,0 +1,4 @@ +--format documentation +--color +--pattern "spec/*/*_spec.rb" +#--backtrace diff --git a/puppet/modules/sshd/.travis.yml b/puppet/modules/sshd/.travis.yml new file mode 100644 index 00000000..7bd2a2bc --- /dev/null +++ b/puppet/modules/sshd/.travis.yml @@ -0,0 +1,27 @@ +before_install: +  - gem update --system 2.1.11 +  - gem --version +rvm: +  - 1.8.7 +  - 1.9.3 +  - 2.0.0 +script: 'bundle exec rake spec' +env: +  - PUPPET_VERSION="~> 2.7.0" +  - PUPPET_VERSION="~> 3.0.0" +  - PUPPET_VERSION="~> 3.1.0" +  - PUPPET_VERSION="~> 3.2.0" +  - PUPPET_VERSION="~> 3.3.0" +  - PUPPET_VERSION="~> 3.4.0" +matrix: +  exclude: +    # No support for Ruby 1.9 before Puppet 2.7 +    - rvm: 1.9.3 +      env: PUPPET_VERSION=2.6.0 +    # No support for Ruby 2.0 before Puppet 3.2 +    - rvm: 2.0.0 +      env: PUPPET_VERSION="~> 2.7.0" +    - rvm: 2.0.0 +      env: PUPPET_VERSION="~> 3.0.0" +    - rvm: 2.0.0 +      env: PUPPET_VERSION="~> 3.1.0" diff --git a/puppet/modules/sshd/Gemfile b/puppet/modules/sshd/Gemfile new file mode 100644 index 00000000..ef74f90e --- /dev/null +++ b/puppet/modules/sshd/Gemfile @@ -0,0 +1,14 @@ +source 'https://rubygems.org' + +group :development, :test do +  gem 'puppet',  '>= 2.7.0' +  gem 'puppet-lint', '>=0.3.2' +  gem 'puppetlabs_spec_helper', '>=0.2.0' +  gem 'rake',         '>=0.9.2.2' +  gem 'librarian-puppet', '>=0.9.10' +  gem 'rspec-system-puppet',     :require => false +  gem 'serverspec',              :require => false +  gem 'rspec-system-serverspec', :require => false +  gem 'rspec-hiera-puppet' +  gem 'rspec-puppet', :git => 'https://github.com/rodjek/rspec-puppet.git' +end
\ No newline at end of file diff --git a/puppet/modules/sshd/Gemfile.lock b/puppet/modules/sshd/Gemfile.lock new file mode 100644 index 00000000..0c2c58e9 --- /dev/null +++ b/puppet/modules/sshd/Gemfile.lock @@ -0,0 +1,116 @@ +GIT +  remote: https://github.com/rodjek/rspec-puppet.git +  revision: c44381a240ec420d4ffda7bffc55ee4d9c08d682 +  specs: +    rspec-puppet (1.0.1) +      rspec + +GEM +  remote: https://rubygems.org/ +  specs: +    builder (3.2.2) +    diff-lcs (1.2.5) +    excon (0.31.0) +    facter (1.7.4) +    fog (1.19.0) +      builder +      excon (~> 0.31.0) +      formatador (~> 0.2.0) +      mime-types +      multi_json (~> 1.0) +      net-scp (~> 1.1) +      net-ssh (>= 2.1.3) +      nokogiri (~> 1.5) +      ruby-hmac +    formatador (0.2.4) +    hiera (1.3.1) +      json_pure +    hiera-puppet (1.0.0) +      hiera (~> 1.0) +    highline (1.6.20) +    json (1.8.1) +    json_pure (1.8.1) +    kwalify (0.7.2) +    librarian-puppet (0.9.10) +      json +      thor (~> 0.15) +    metaclass (0.0.2) +    mime-types (1.25.1) +    mocha (1.0.0) +      metaclass (~> 0.0.1) +    multi_json (1.8.4) +    net-scp (1.1.2) +      net-ssh (>= 2.6.5) +    net-ssh (2.7.0) +    nokogiri (1.5.11) +    puppet (3.4.2) +      facter (~> 1.6) +      hiera (~> 1.0) +      rgen (~> 0.6.5) +    puppet-lint (0.3.2) +    puppetlabs_spec_helper (0.4.1) +      mocha (>= 0.10.5) +      rake +      rspec (>= 2.9.0) +      rspec-puppet (>= 0.1.1) +    rake (10.1.1) +    rbvmomi (1.8.1) +      builder +      nokogiri (>= 1.4.1) +      trollop +    rgen (0.6.6) +    rspec (2.14.1) +      rspec-core (~> 2.14.0) +      rspec-expectations (~> 2.14.0) +      rspec-mocks (~> 2.14.0) +    rspec-core (2.14.7) +    rspec-expectations (2.14.4) +      diff-lcs (>= 1.1.3, < 2.0) +    rspec-hiera-puppet (1.0.0) +      hiera (>= 1.0) +      hiera-puppet (>= 1.0) +      puppet (>= 3.0) +      rspec +      rspec-puppet +    rspec-mocks (2.14.4) +    rspec-system (2.8.0) +      fog (~> 1.18) +      kwalify (~> 0.7.2) +      mime-types (~> 1.16) +      net-scp (~> 1.1) +      net-ssh (~> 2.7) +      nokogiri (~> 1.5.10) +      rbvmomi (~> 1.6) +      rspec (~> 2.14) +      systemu (~> 2.5) +    rspec-system-puppet (2.2.1) +      rspec-system (~> 2.0) +    rspec-system-serverspec (2.0.1) +      rspec-system (~> 2.0) +      serverspec (~> 0.0) +      specinfra (~> 0.0) +    ruby-hmac (0.4.0) +    serverspec (0.14.4) +      highline +      net-ssh +      rspec (>= 2.13.0) +      specinfra (>= 0.1.0) +    specinfra (0.4.1) +    systemu (2.6.0) +    thor (0.18.1) +    trollop (2.0) + +PLATFORMS +  ruby + +DEPENDENCIES +  librarian-puppet (>= 0.9.10) +  puppet (>= 2.7.0) +  puppet-lint (>= 0.3.2) +  puppetlabs_spec_helper (>= 0.2.0) +  rake (>= 0.9.2.2) +  rspec-hiera-puppet +  rspec-puppet! +  rspec-system-puppet +  rspec-system-serverspec +  serverspec diff --git a/puppet/modules/sshd/LICENSE b/puppet/modules/sshd/LICENSE new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/puppet/modules/sshd/LICENSE @@ -0,0 +1,674 @@ +                    GNU GENERAL PUBLIC LICENSE +                       Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +                            Preamble + +  The GNU General Public License is a free, copyleft license for +software and other kinds of works. + +  The licenses for most software and other practical works are designed +to take away your freedom to share and change the works.  By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users.  We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors.  You can apply it to +your programs, too. + +  When we speak of free software, we are referring to freedom, not +price.  Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +  To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights.  Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + +  For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received.  You must make sure that they, too, receive +or can get the source code.  And you must show them these terms so they +know their rights. + +  Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + +  For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software.  For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + +  Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so.  This is fundamentally incompatible with the aim of +protecting users' freedom to change the software.  The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable.  Therefore, we +have designed this version of the GPL to prohibit the practice for those +products.  If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + +  Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary.  To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + +  The precise terms and conditions for copying, distribution and +modification follow. + +                       TERMS AND CONDITIONS + +  0. Definitions. + +  "This License" refers to version 3 of the GNU General Public License. + +  "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +  "The Program" refers to any copyrightable work licensed under this +License.  Each licensee is addressed as "you".  "Licensees" and +"recipients" may be individuals or organizations. + +  To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy.  The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + +  A "covered work" means either the unmodified Program or a work based +on the Program. + +  To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy.  Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +  To "convey" a work means any kind of propagation that enables other +parties to make or receive copies.  Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +  An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License.  If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +  1. Source Code. + +  The "source code" for a work means the preferred form of the work +for making modifications to it.  "Object code" means any non-source +form of a work. + +  A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +  The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form.  A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +  The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities.  However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work.  For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +  The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +  The Corresponding Source for a work in source code form is that +same work. + +  2. Basic Permissions. + +  All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met.  This License explicitly affirms your unlimited +permission to run the unmodified Program.  The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work.  This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +  You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force.  You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright.  Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +  Conveying under any other circumstances is permitted solely under +the conditions stated below.  Sublicensing is not allowed; section 10 +makes it unnecessary. + +  3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +  No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +  When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +  4. Conveying Verbatim Copies. + +  You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +  You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +  5. Conveying Modified Source Versions. + +  You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + +    a) The work must carry prominent notices stating that you modified +    it, and giving a relevant date. + +    b) The work must carry prominent notices stating that it is +    released under this License and any conditions added under section +    7.  This requirement modifies the requirement in section 4 to +    "keep intact all notices". + +    c) You must license the entire work, as a whole, under this +    License to anyone who comes into possession of a copy.  This +    License will therefore apply, along with any applicable section 7 +    additional terms, to the whole of the work, and all its parts, +    regardless of how they are packaged.  This License gives no +    permission to license the work in any other way, but it does not +    invalidate such permission if you have separately received it. + +    d) If the work has interactive user interfaces, each must display +    Appropriate Legal Notices; however, if the Program has interactive +    interfaces that do not display Appropriate Legal Notices, your +    work need not make them do so. + +  A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit.  Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +  6. Conveying Non-Source Forms. + +  You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + +    a) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by the +    Corresponding Source fixed on a durable physical medium +    customarily used for software interchange. + +    b) Convey the object code in, or embodied in, a physical product +    (including a physical distribution medium), accompanied by a +    written offer, valid for at least three years and valid for as +    long as you offer spare parts or customer support for that product +    model, to give anyone who possesses the object code either (1) a +    copy of the Corresponding Source for all the software in the +    product that is covered by this License, on a durable physical +    medium customarily used for software interchange, for a price no +    more than your reasonable cost of physically performing this +    conveying of source, or (2) access to copy the +    Corresponding Source from a network server at no charge. + +    c) Convey individual copies of the object code with a copy of the +    written offer to provide the Corresponding Source.  This +    alternative is allowed only occasionally and noncommercially, and +    only if you received the object code with such an offer, in accord +    with subsection 6b. + +    d) Convey the object code by offering access from a designated +    place (gratis or for a charge), and offer equivalent access to the +    Corresponding Source in the same way through the same place at no +    further charge.  You need not require recipients to copy the +    Corresponding Source along with the object code.  If the place to +    copy the object code is a network server, the Corresponding Source +    may be on a different server (operated by you or a third party) +    that supports equivalent copying facilities, provided you maintain +    clear directions next to the object code saying where to find the +    Corresponding Source.  Regardless of what server hosts the +    Corresponding Source, you remain obligated to ensure that it is +    available for as long as needed to satisfy these requirements. + +    e) Convey the object code using peer-to-peer transmission, provided +    you inform other peers where the object code and Corresponding +    Source of the work are being offered to the general public at no +    charge under subsection 6d. + +  A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +  A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling.  In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage.  For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product.  A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +  "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source.  The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +  If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information.  But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +  The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed.  Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +  Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +  7. Additional Terms. + +  "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law.  If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +  When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it.  (Additional permissions may be written to require their own +removal in certain cases when you modify the work.)  You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +  Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + +    a) Disclaiming warranty or limiting liability differently from the +    terms of sections 15 and 16 of this License; or + +    b) Requiring preservation of specified reasonable legal notices or +    author attributions in that material or in the Appropriate Legal +    Notices displayed by works containing it; or + +    c) Prohibiting misrepresentation of the origin of that material, or +    requiring that modified versions of such material be marked in +    reasonable ways as different from the original version; or + +    d) Limiting the use for publicity purposes of names of licensors or +    authors of the material; or + +    e) Declining to grant rights under trademark law for use of some +    trade names, trademarks, or service marks; or + +    f) Requiring indemnification of licensors and authors of that +    material by anyone who conveys the material (or modified versions of +    it) with contractual assumptions of liability to the recipient, for +    any liability that these contractual assumptions directly impose on +    those licensors and authors. + +  All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10.  If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term.  If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +  If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +  Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +  8. Termination. + +  You may not propagate or modify a covered work except as expressly +provided under this License.  Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +  However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +  Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +  Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License.  If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +  9. Acceptance Not Required for Having Copies. + +  You are not required to accept this License in order to receive or +run a copy of the Program.  Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance.  However, +nothing other than this License grants you permission to propagate or +modify any covered work.  These actions infringe copyright if you do +not accept this License.  Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +  10. Automatic Licensing of Downstream Recipients. + +  Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License.  You are not responsible +for enforcing compliance by third parties with this License. + +  An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations.  If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +  You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License.  For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +  11. Patents. + +  A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based.  The +work thus licensed is called the contributor's "contributor version". + +  A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version.  For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +  Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +  In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement).  To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +  If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients.  "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +  If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +  A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License.  You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +  Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +  12. No Surrender of Others' Freedom. + +  If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License.  If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all.  For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +  13. Use with the GNU Affero General Public License. + +  Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work.  The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + +  14. Revised Versions of this License. + +  The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time.  Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +  Each version is given a distinguishing version number.  If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation.  If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + +  If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +  Later license versions may give you additional or different +permissions.  However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +  15. Disclaimer of Warranty. + +  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +  16. Limitation of Liability. + +  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +  17. Interpretation of Sections 15 and 16. + +  If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +                     END OF TERMS AND CONDITIONS + +            How to Apply These Terms to Your New Programs + +  If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +  To do so, attach the following notices to the program.  It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + +    <one line to give the program's name and a brief idea of what it does.> +    Copyright (C) <year>  <name of author> + +    This program is free software: you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation, either version 3 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program.  If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + +  If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + +    <program>  Copyright (C) <year>  <name of author> +    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +    This is free software, and you are welcome to redistribute it +    under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License.  Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + +  You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + +  The GNU General Public License does not permit incorporating your program +into proprietary programs.  If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library.  If this is what you want to do, use the GNU Lesser General +Public License instead of this License.  But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/puppet/modules/sshd/Modulefile b/puppet/modules/sshd/Modulefile new file mode 100644 index 00000000..5e4f92d6 --- /dev/null +++ b/puppet/modules/sshd/Modulefile @@ -0,0 +1,10 @@ +name    'puppet-sshd' +version '0.1.0' +source 'https://github.com/duritong/puppet-sshd' +author 'duritong' +license 'Apache License, Version 2.0' +summary 'ssh daemon configuration' +description 'Manages sshd_config' +project_page 'https://github.com/duritong/puppet-sshd' + +dependency 'puppetlabs/stdlib', '>= 2.0.0'
\ No newline at end of file diff --git a/puppet/modules/sshd/Puppetfile b/puppet/modules/sshd/Puppetfile new file mode 100644 index 00000000..166d3b4d --- /dev/null +++ b/puppet/modules/sshd/Puppetfile @@ -0,0 +1,3 @@ +forge 'http://forge.puppetlabs.com' + +mod 'puppetlabs/stdlib', '>=2.0.0'
\ No newline at end of file diff --git a/puppet/modules/sshd/Puppetfile.lock b/puppet/modules/sshd/Puppetfile.lock new file mode 100644 index 00000000..f9381858 --- /dev/null +++ b/puppet/modules/sshd/Puppetfile.lock @@ -0,0 +1,8 @@ +FORGE +  remote: http://forge.puppetlabs.com +  specs: +    puppetlabs/stdlib (4.1.0) + +DEPENDENCIES +  puppetlabs/stdlib (>= 2.0.0) + diff --git a/puppet/modules/sshd/README.md b/puppet/modules/sshd/README.md new file mode 100644 index 00000000..77e4d29b --- /dev/null +++ b/puppet/modules/sshd/README.md @@ -0,0 +1,247 @@ +# Puppet SSH Module + +[](https://travis-ci.org/duritong/puppet-sshd) + +This puppet module manages OpenSSH configuration and services. + +**!! Upgrade Notice (05/2015) !!** + +The hardened_ssl parameter name was changed to simply 'hardened'. + +**!! Upgrade Notice (01/2013) !!** + +This module now uses parameterized classes, where it used global variables +before. So please whatch out before pulling, you need to change the +class declarations in your manifest ! + + +### Dependencies + +This module requires puppet => 2.6, and the following modules are required +pre-dependencies: + +- [puppetlabs/stdlib](https://github.com/puppetlabs/puppetlabs-stdlib) >= 2.x + +## OpenSSH Server + +On a node where you wish to have an openssh server installed, you should +include + +```puppet +class { 'sshd': } +``` + +on that node. If you need to configure any aspects of sshd_config, set the variables before the include. Or you can adjust many parameters: + +```puppet +class { 'sshd': +  ports             => [ 20002 ], +  permit_root_login => 'no', +} +``` + +See Configurable Variables below for what you can set. + +### Nagios + +To have nagios checks setup automatically for sshd services, simply set +`manage_nagios` to `true` for that class. If you want to disable ssh +nagios checking for a particular node (such as when ssh is firewalled), then you +can set the class parameter `nagios_check_ssh` to `false` and that node will not be +monitored. + +Nagios will automatically check the ports defined in `ports`, and the +hostname specified by `nagios_check_ssh_hostname`. + +Note that if you need to use some specific logic to decide whether or not to +create a nagios service check, you should set $manage_nagios to false, and +use sshd::nagios from within your own manifests. You'll also need to manually +specify the port to that define. By default, if the $port parameter is not +specified, it will use the resource name as the port (e.g. if you call it like +this: `sshd::nagios { '22': }` ) + +NOTE: this requires that you are using the shared-nagios puppet module which +supports the nagios native types via `nagios::service`: + +https://gitlab.com/shared-puppet-modules-group/sshd + +### Firewall + +If you wish to have firewall rules setup automatically for you, using shorewall, +you will need to set: `use_shorewall => true`. The `ports` that you have +specified will automatically be used. + +NOTE: This requires that you are using the shared-shorewall puppet module: +git://labs.riseup.net/shared-shorewall + + +### Configurable variables + +Configuration of sshd is strict, and may not fit all needs, however there are a +number of variables that you can consider configuring. The defaults are set to +the distribution shipped sshd_config file defaults. + +To set any of these variables, simply set them as variables in your manifests, +before the class is included, for example: + +```puppet +class {'sshd': +  listen_address => ['10.0.0.1', '192.168.0.1'], +  use_pam        => yes +} +``` + +If you need to install a version of the ssh daemon or client package other than +the default one that would be installed by `ensure => installed`, then you can +set the following variables: + +```puppet +class {'sshd': +  ensure_version => "1:5.2p2-6" +} +``` + +The following is a list of the currently available variables: + +  - `listen_address` +        specify the addresses sshd should listen on set this to `['10.0.0.1', '192.168.0.1']` to have it listen on both addresses, or leave it unset to listen on all Default: empty -> results in listening on `0.0.0.0` +  - `allowed_users` +    list of usernames separated by spaces.  set this for example to `"foobar +    root"` to ensure that only user foobar and root might login.  Default: empty +    -> no restriction is set +  - `allowed_groups` +    list of groups separated by spaces. set this for example to `"wheel sftponly"` +    to ensure that only users in the groups wheel and sftponly might login. +    Default: empty -> no restriction is set Note: This is set after +    `allowed_users`, take care of the behaviour if you use these 2 options +    together. +  - `use_pam` if you want to use pam or not for authenticaton. Values: +    - `no` (default) +    - `yes` +  - `permit_root_login` If you want to allow root logins or not. Valid values: +    - `yes` +    - `no` +    - `without-password` (default) +    - `forced-commands-only` +  - `password_authentication` +    If you want to enable password authentication or not. Valid values: +    - `yes` +    - `no` (default) +  - `kerberos_authentication` +    If you want the password that is provided by the user to be validated +    through the Kerberos KDC. To use this option the server needs a Kerberos +    servtab which allows the verification of the KDC's identity. Valid values: +    - `yes` +    - `no` (default) +  - `kerberos_orlocalpasswd` If password authentication through Kerberos fails, then the password will be validated via any additional local mechanism.  Valid values: +    - `yes` (default) +    - `no` +  - `kerberos_ticketcleanup` Destroy the user's ticket cache file on logout?  Valid values: +    - `yes` (default) +    - `no` +  - `gssapi_authentication` Authenticate users based on GSSAPI? Valid values: +    - `yes` +    - `no` (default) +  - `gssapi_cleanupcredentials` Destroy user's credential cache on logout? Valid values: +    - `yes` (default) +    - `no` +  - `challenge_response_authentication` If you want to enable ChallengeResponseAuthentication or not When disabled, s/key passwords are disabled. Valid values: +    - `yes` +    - `no` (default) +  - `tcp_forwarding` If you want to enable TcpForwarding. Valid values: +    - `yes` +    - `no` (default) +  - `x11_forwarding` If you want to enable x11 forwarding. Valid values: +    - `yes` +    - `no` (default) +  - `agent_forwarding` If you want to allow ssh-agent forwarding. Valid values: +    - `yes` +    - `no` (default) +  - `pubkey_authentication` If you want to enable public key authentication. Valid values: +    - `yes` (default) +    - `no` +  - `rsa_authentication` If you want to enable RSA Authentication. Valid values: +    - `yes` +    - `no` (default) +  - `rhosts_rsa_authentication` +    If you want to enable rhosts RSA Authentication. Valid values: +    - `yes` +    - `no` (default) +  - `hostbased_authentication` If you want to enable `HostbasedAuthentication`. Valid values: +    - `yes` +    - `no` (default) +  - `strict_modes` If you want to set `StrictModes` (check file modes/ownership before accepting login). Valid values: +    - `yes` (default) +    - `no` +  - `permit_empty_passwords` +    If you want enable PermitEmptyPasswords to allow empty passwords. Valid +    Values: +    - `yes` +    - `no` (default) +  - `ports` If you want to specify a list of ports other than the default `22`; Default: `[22]` +  - `authorized_keys_file` +    Set this to the location of the AuthorizedKeysFile +    (e.g. `/etc/ssh/authorized_keys/%u`). Default: `AuthorizedKeysFile +    %h/.ssh/authorized_keys` +  - `hardened` +    Use only strong ciphers, MAC, KexAlgorithms, etc. +    Values: +    - `no` (default) +    - `yes` +  - `print_motd` +    Show the Message of the day when a user logs in. +  - `sftp_subsystem` +    Set a different sftp-subystem than the default one. Might be interesting for +    sftponly usage. Default: empty -> no change of the default +  - `head_additional_options` +    Set this to any additional sshd_options which aren't listed above. Anything +    set here will be added to the beginning of the sshd_config file. This option +    might be useful to define complicated Match Blocks. This string is going to +    be included, like it is defined. So take care! Default: empty -> not added. +  - `tail_additional_options` Set this to any additional sshd_options which aren't listed above. Anything set here will be added to the end of the sshd_config file. This option might be useful to define complicated Match Blocks. This string is going to be included, like it is defined. So take care! Default: empty -> not added. +  - `shared_ip` Whether the server uses a shared network IP address. If it does, then we don't want it to export an rsa key for its IP address. Values: +  - `no` (default) +  - `yes` + + +### Defines and functions + +Deploy authorized_keys file with the define `authorized_key`. + +Generate a public/private keypair with the ssh_keygen function. For example, the +following will generate ssh keys and put the different parts of the key into +variables: + +```puppet +$ssh_keys = ssh_keygen("${$ssh_key_basepath}/backup/keys/${::fqdn}/${backup_host}") +$public_key = split($ssh_keys[1],' ') +$sshkey_type => $public_key[0] +$sshkey => $public_key[1] +``` + +## Client + + +On a node where you wish to have the ssh client managed, you can do: + +```puppet +class{'sshd::client': + +} +``` + +in the node definition. This will install the appropriate package. + +## License + + - Copyright 2008-2011, Riseup Labs micah@riseup.net + - Copyright 2008, admin(at)immerda.ch + - Copyright 2008, Puzzle ITC GmbH + - Marcel Härry haerry+puppet(at)puzzle.ch + - Simon Josi josi+puppet(at)puzzle.ch + +This program is free software; you can redistribute +it and/or modify it under the terms of the GNU +General Public License version 3 as published by +the Free Software Foundation. + diff --git a/puppet/modules/sshd/Rakefile b/puppet/modules/sshd/Rakefile new file mode 100644 index 00000000..e3213518 --- /dev/null +++ b/puppet/modules/sshd/Rakefile @@ -0,0 +1,16 @@ +require 'bundler' +Bundler.require(:rake) + +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' +require 'rspec-system/rake_task' + +PuppetLint.configuration.log_format = '%{path}:%{linenumber}:%{KIND}: %{message}' +PuppetLint.configuration.send("disable_80chars") + +puppet_module='sshd' +task :librarian_spec_prep do +  sh 'librarian-puppet install --path=spec/fixtures/modules/' +end +task :spec_prep => :librarian_spec_prep +task :default => [:spec, :lint] diff --git a/puppet/modules/sshd/files/autossh.init.d b/puppet/modules/sshd/files/autossh.init.d new file mode 100644 index 00000000..92bd5f43 --- /dev/null +++ b/puppet/modules/sshd/files/autossh.init.d @@ -0,0 +1,164 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides:          AutoSSH +# Required-Start:    $local_fs $network $remote_fs $syslog +# Required-Stop:     $local_fs $network $remote_fs $syslog +# Default-Start:     2 3 4 5 +# Default-Stop:      0 1 6 +# Short-Description: start the autossh daemon +# Description:       start the autossh daemon +### END INIT INFO + +# Author: Antoine Beaupré <anarcat@koumbit.org> + +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="autossh" +NAME=autossh +USER=$NAME +DAEMON=/usr/bin/autossh +DAEMON_ARGS="-f" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +AUTOSSH_PIDFILE=$PIDFILE +export AUTOSSH_PIDFILE + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ +	# Return +	#   0 if daemon has been started +	#   1 if daemon was already running +	#   2 if daemon could not be started +        start-stop-daemon --start --quiet --user $USER --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ +		|| return 1 +	start-stop-daemon --start --quiet --user $USER --chuid $USER --pidfile $PIDFILE --exec $DAEMON -- \ +		$DAEMON_ARGS \ +		|| return 2 +	# The above code will not work for interpreted scripts, use the next +	# six lines below instead (Ref: #643337, start-stop-daemon(8) ) +	#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \ +	#	--name $NAME --test > /dev/null \ +	#	|| return 1 +	#start-stop-daemon --start --quiet --pidfile $PIDFILE --startas $DAEMON \ +	#	--name $NAME -- $DAEMON_ARGS \ +	#	|| return 2 + +	# Add code here, if necessary, that waits for the process to be ready +	# to handle requests from services started subsequently which depend +	# on this one.  As a last resort, sleep for some time. +} + +# +# Function that stops the daemon/service +# +do_stop() +{ +	# Return +	#   0 if daemon has been stopped +	#   1 if daemon was already stopped +	#   2 if daemon could not be stopped +	#   other if a failure occurred +	start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --user $USER --name $NAME +	RETVAL="$?" +	[ "$RETVAL" = 2 ] && return 2 +	# Wait for children to finish too if this is a daemon that forks +	# and if the daemon is only ever run from this initscript. +	# If the above conditions are not satisfied then add some other code +	# that waits for the process to drop all resources that could be +	# needed by services started subsequently.  A last resort is to +	# sleep for some time. +	start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --user $USER --exec $DAEMON +	[ "$?" = 2 ] && return 2 +	# Many daemons don't delete their pidfiles when they exit. +	rm -f $PIDFILE +	return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { +	# +	# If the daemon can reload its configuration without +	# restarting (for example, when it is sent a SIGHUP), +	# then implement that here. +	# +	start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME +	return 0 +} + +case "$1" in +  start) +	[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" +	do_start +	case "$?" in +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; +	esac +	;; +  stop) +	[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" +	do_stop +	case "$?" in +		0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; +		2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; +	esac +	;; +  status) +	status_of_proc -p "$PIDFILE" "$DAEMON" "$NAME" && exit 0 || exit $? +	;; +  reload|force-reload) +        log_daemon_msg "Reloading $DESC" "$NAME" +	do_reload +	log_end_msg $? +	;; +  restart) +	# +	# If the "reload" option is implemented then remove the +	# 'force-reload' alias +	# +	log_daemon_msg "Restarting $DESC" "$NAME" +	do_stop +	case "$?" in +	  0|1) +		do_start +		case "$?" in +			0) log_end_msg 0 ;; +			1) log_end_msg 1 ;; # Old process is still running +			*) log_end_msg 1 ;; # Failed to start +		esac +		;; +	  *) +		# Failed to stop +		log_end_msg 1 +		;; +	esac +	;; +  *) +	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 +	echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 +	exit 3 +	;; +esac + +: diff --git a/puppet/modules/sshd/lib/facter/ssh_version.rb b/puppet/modules/sshd/lib/facter/ssh_version.rb new file mode 100644 index 00000000..51d8a00f --- /dev/null +++ b/puppet/modules/sshd/lib/facter/ssh_version.rb @@ -0,0 +1,5 @@ +Facter.add("ssh_version") do +  setcode do +    ssh_version = Facter::Util::Resolution.exec('ssh -V 2>&1 1>/dev/null').chomp.split(' ')[0].split('_')[1] +  end +end diff --git a/puppet/modules/sshd/lib/puppet/parser/functions/ssh_keygen.rb b/puppet/modules/sshd/lib/puppet/parser/functions/ssh_keygen.rb new file mode 100644 index 00000000..e304f242 --- /dev/null +++ b/puppet/modules/sshd/lib/puppet/parser/functions/ssh_keygen.rb @@ -0,0 +1,30 @@ +Puppet::Parser::Functions::newfunction(:ssh_keygen, :type => :rvalue, :doc => +  "Returns an array containing the ssh private and public (in this order) key +  for a certain private key path. +  It will generate the keypair if both do not exist. It will also generate +  the directory hierarchy if required. +  It accepts only fully qualified paths, everything else will fail.") do |args| +    raise Puppet::ParseError, "Wrong number of arguments" unless args.to_a.length == 1 +    private_key_path = args.to_a[0] +    raise Puppet::ParseError, "Only fully qualified paths are accepted (#{private_key_path})" unless private_key_path =~ /^\/.+/ +    public_key_path = "#{private_key_path}.pub" +    raise Puppet::ParseError, "Either only the private or only the public key exists" if File.exists?(private_key_path) ^ File.exists?(public_key_path) +    [private_key_path,public_key_path].each do |path| +      raise Puppet::ParseError, "#{path} is a directory" if File.directory?(path) +    end + +    dir = File.dirname(private_key_path) +    unless File.directory?(dir) +      require 'fileutils' +      FileUtils.mkdir_p(dir, :mode => 0700) +    end +    unless [private_key_path,public_key_path].all?{|path| File.exists?(path) } +      executor = (Facter.value(:puppetversion).to_i < 3) ? Puppet::Util : Puppet::Util::Execution +      output = executor.execute( +        ['/usr/bin/ssh-keygen','-t', 'rsa', '-b', '4096',  +         '-f', private_key_path, '-P', '', '-q']) +      raise Puppet::ParseError, "Something went wrong during key generation! Output: #{output}" unless output.empty? +    end +    [File.read(private_key_path),File.read(public_key_path)] +end + diff --git a/puppet/modules/sshd/manifests/autossh.pp b/puppet/modules/sshd/manifests/autossh.pp new file mode 100644 index 00000000..5650584a --- /dev/null +++ b/puppet/modules/sshd/manifests/autossh.pp @@ -0,0 +1,40 @@ +class sshd::autossh($host, +                    $port = undef, # this should be a remote->local hash +                    $remote_user = undef, +                    $user = 'root', +                    $pidfile = '/var/run/autossh.pid', +) { +  if $port { +    $port_ensure = $port +  } +  else { +    # random port between 10000 and 20000 +    $port_ensure = fqdn_rand(10000) + 10000 +  } +  if $remote_user { +    $remote_user_ensure = $remote_user +  } +  else { +    $remote_user_ensure = "host-$fqdn" +  } +  file { +    '/etc/init.d/autossh': +      mode   => '0555', +      source => 'puppet:///modules/sshd/autossh.init.d'; +    '/etc/default/autossh': +      mode    => '0444', +      content => "USER=$user\nPIDFILE=$pidfile\nDAEMON_ARGS='-M0 -f -o ServerAliveInterval=15 -o ServerAliveCountMax=4 -q -N -R $port_ensure:localhost:22 $remote_user_ensure@$host'\n"; +  } +  package { 'autossh': +    ensure => present, +  } +  service { 'autossh': +    ensure    => running, +    enable    => true, +    subscribe => [ +                  File['/etc/init.d/autossh'], +                  File['/etc/default/autossh'], +                  Package['autossh'], +                  ], +  } +} diff --git a/puppet/modules/sshd/manifests/base.pp b/puppet/modules/sshd/manifests/base.pp new file mode 100644 index 00000000..dda9f26c --- /dev/null +++ b/puppet/modules/sshd/manifests/base.pp @@ -0,0 +1,41 @@ +# The base class to setup the common things. +# This is a private class and will always be used +# throught the sshd class itself. +class sshd::base { + +  $sshd_config_content = $::operatingsystem ? { +    'CentOS'  => template("sshd/sshd_config/${::operatingsystem}_${::operatingsystemmajrelease}.erb"), +    default   => $::lsbdistcodename ? { +      ''      => template("sshd/sshd_config/${::operatingsystem}.erb"), +      default => template("sshd/sshd_config/${::operatingsystem}_${::lsbdistcodename}.erb") +    } +  } + +  file { 'sshd_config': +    ensure  => present, +    path    => '/etc/ssh/sshd_config', +    content => $sshd_config_content, +    notify  => Service[sshd], +    owner   => root, +    group   => 0, +    mode    => '0600'; +  } + +  # Now add the key, if we've got one +  case $::sshrsakey { +    '': { info("no sshrsakey on ${::fqdn}") } +    default: { +      # only export sshkey when storedconfigs is enabled +      if $::sshd::use_storedconfigs { +        include ::sshd::sshkey +      } +    } +  } +  service{'sshd': +    ensure    => running, +    name      => 'sshd', +    enable    => true, +    hasstatus => true, +    require   => File[sshd_config], +  } +} diff --git a/puppet/modules/sshd/manifests/client.pp b/puppet/modules/sshd/manifests/client.pp new file mode 100644 index 00000000..84dd7abc --- /dev/null +++ b/puppet/modules/sshd/manifests/client.pp @@ -0,0 +1,22 @@ +# manifests/client.pp + +class sshd::client( +  $shared_ip = 'no', +  $ensure_version = 'installed', +  $manage_shorewall = false +) { + +  case $::operatingsystem { +    debian,ubuntu: { include sshd::client::debian } +    default: { +      case $::kernel { +        linux: { include sshd::client::linux } +        default: { include sshd::client::base } +      } +    } +  } + +  if $manage_shorewall{ +    include shorewall::rules::out::ssh +  } +} diff --git a/puppet/modules/sshd/manifests/client/base.pp b/puppet/modules/sshd/manifests/client/base.pp new file mode 100644 index 00000000..4925c2d0 --- /dev/null +++ b/puppet/modules/sshd/manifests/client/base.pp @@ -0,0 +1,15 @@ +class sshd::client::base { +  # this is needed because the gid might have changed +  file { '/etc/ssh/ssh_known_hosts': +    ensure => present, +    mode   => '0644', +    owner  => root, +    group  => 0; +  } + +  # Now collect all server keys +  case $sshd::client::shared_ip { +    no:  { Sshkey <<||>> } +    yes: { Sshkey <<| tag == fqdn |>> } +  } +} diff --git a/puppet/modules/sshd/manifests/client/debian.pp b/puppet/modules/sshd/manifests/client/debian.pp new file mode 100644 index 00000000..2aaf3fb1 --- /dev/null +++ b/puppet/modules/sshd/manifests/client/debian.pp @@ -0,0 +1,5 @@ +class sshd::client::debian inherits sshd::client::linux { +  Package['openssh-clients']{ +    name => 'openssh-client', +  } +} diff --git a/puppet/modules/sshd/manifests/client/linux.pp b/puppet/modules/sshd/manifests/client/linux.pp new file mode 100644 index 00000000..0c420be2 --- /dev/null +++ b/puppet/modules/sshd/manifests/client/linux.pp @@ -0,0 +1,5 @@ +class sshd::client::linux inherits sshd::client::base { +  package {'openssh-clients': +    ensure => $sshd::client::ensure_version, +  } +} diff --git a/puppet/modules/sshd/manifests/debian.pp b/puppet/modules/sshd/manifests/debian.pp new file mode 100644 index 00000000..d827078a --- /dev/null +++ b/puppet/modules/sshd/manifests/debian.pp @@ -0,0 +1,13 @@ +class sshd::debian inherits sshd::linux { + +  Package[openssh]{ +    name => 'openssh-server', +  } + +  Service[sshd]{ +    name       => 'ssh', +    pattern    => 'sshd', +    hasstatus  => true, +    hasrestart => true, +  } +} diff --git a/puppet/modules/sshd/manifests/gentoo.pp b/puppet/modules/sshd/manifests/gentoo.pp new file mode 100644 index 00000000..631f3d19 --- /dev/null +++ b/puppet/modules/sshd/manifests/gentoo.pp @@ -0,0 +1,5 @@ +class sshd::gentoo inherits sshd::linux { +  Package[openssh]{ +    category => 'net-misc', +  } +} diff --git a/puppet/modules/sshd/manifests/init.pp b/puppet/modules/sshd/manifests/init.pp new file mode 100644 index 00000000..b4157418 --- /dev/null +++ b/puppet/modules/sshd/manifests/init.pp @@ -0,0 +1,92 @@ +# manage an sshd installation +class sshd( +  $manage_nagios = false, +  $nagios_check_ssh_hostname = 'absent', +  $ports = [ 22 ], +  $shared_ip = 'no', +  $ensure_version = 'installed', +  $listen_address = [ '0.0.0.0', '::' ], +  $allowed_users = '', +  $allowed_groups = '', +  $use_pam = 'no', +  $permit_root_login = 'without-password', +  $password_authentication = 'no', +  $kerberos_authentication = 'no', +  $kerberos_orlocalpasswd = 'yes', +  $kerberos_ticketcleanup = 'yes', +  $gssapi_authentication = 'no', +  $gssapi_cleanupcredentials = 'yes', +  $tcp_forwarding = 'no', +  $x11_forwarding = 'no', +  $agent_forwarding = 'no', +  $challenge_response_authentication = 'no', +  $pubkey_authentication = 'yes', +  $rsa_authentication = 'no', +  $strict_modes = 'yes', +  $ignore_rhosts = 'yes', +  $rhosts_rsa_authentication = 'no', +  $hostbased_authentication = 'no', +  $permit_empty_passwords = 'no', +  $authorized_keys_file = $::osfamily ? { +    Debian => $::lsbmajdistrelease ? { +      6       => '%h/.ssh/authorized_keys', +      default => '%h/.ssh/authorized_keys %h/.ssh/authorized_keys2', +    }, +    RedHat => $::operatingsystemmajrelease ? { +      5       => '%h/.ssh/authorized_keys', +      6       => '%h/.ssh/authorized_keys', +      default => '%h/.ssh/authorized_keys %h/.ssh/authorized_keys2', +    }, +    OpenBSD => '%h/.ssh/authorized_keys', +    default => '%h/.ssh/authorized_keys %h/.ssh/authorized_keys2', +  }, +  $hardened = 'no', +  $sftp_subsystem = '', +  $head_additional_options = '', +  $tail_additional_options = '', +  $print_motd = 'yes', +  $manage_shorewall = false, +  $shorewall_source = 'net', +  $sshkey_ipaddress = $::ipaddress, +  $manage_client = true, +  $hostkey_type = versioncmp($::ssh_version, '6.5') ? { +    /(^1|0)/ => [ 'rsa', 'ed25519' ], +    /-1/    => [ 'rsa', 'dsa' ] +  }, +  $use_storedconfigs = true +) { + +  validate_bool($manage_shorewall) +  validate_bool($manage_client) +  validate_array($listen_address) +  validate_array($ports) + +  if $manage_client { +    class{'sshd::client': +      shared_ip        => $shared_ip, +      ensure_version   => $ensure_version, +      manage_shorewall => $manage_shorewall, +    } +  } + +  case $::operatingsystem { +    gentoo: { include sshd::gentoo } +    redhat,centos: { include sshd::redhat } +    openbsd: { include sshd::openbsd } +    debian,ubuntu: { include sshd::debian } +    default: { include sshd::base } +  } + +  if $manage_nagios { +    sshd::nagios{$ports: +      check_hostname => $nagios_check_ssh_hostname +    } +  } + +  if $manage_shorewall { +    class{'shorewall::rules::ssh': +      ports  => $ports, +      source => $shorewall_source +    } +  } +} diff --git a/puppet/modules/sshd/manifests/libssh2.pp b/puppet/modules/sshd/manifests/libssh2.pp new file mode 100644 index 00000000..403ac7be --- /dev/null +++ b/puppet/modules/sshd/manifests/libssh2.pp @@ -0,0 +1,7 @@ +# manifests/libssh2.pp + +class sshd::libssh2 { +  package{'libssh2': +    ensure => present, +  } +} diff --git a/puppet/modules/sshd/manifests/libssh2/devel.pp b/puppet/modules/sshd/manifests/libssh2/devel.pp new file mode 100644 index 00000000..261e34c8 --- /dev/null +++ b/puppet/modules/sshd/manifests/libssh2/devel.pp @@ -0,0 +1,7 @@ +# manifests/libssh2/devel.pp + +class sshd::libssh2::devel inherits sshd::libssh2 { +  package{"libssh2-devel.${::architecture}": +    ensure => installed, +  } +} diff --git a/puppet/modules/sshd/manifests/linux.pp b/puppet/modules/sshd/manifests/linux.pp new file mode 100644 index 00000000..8628ff5e --- /dev/null +++ b/puppet/modules/sshd/manifests/linux.pp @@ -0,0 +1,8 @@ +class sshd::linux inherits sshd::base { +  package{'openssh': +    ensure => $sshd::ensure_version, +  } +  File[sshd_config]{ +    require +> Package[openssh], +  } +} diff --git a/puppet/modules/sshd/manifests/nagios.pp b/puppet/modules/sshd/manifests/nagios.pp new file mode 100644 index 00000000..6921de91 --- /dev/null +++ b/puppet/modules/sshd/manifests/nagios.pp @@ -0,0 +1,24 @@ +define sshd::nagios( +  $port = 'absent', +  $ensure = 'present', +  $check_hostname = 'absent' +) { +  $real_port = $port ? { +    'absent' => $name, +    default  => $port, +  } +  case $check_hostname { +    'absent': { +      nagios::service{"ssh_port_${name}": +        ensure        => $ensure, +        check_command => "check_ssh_port!${real_port}" +      } +    } +    default: { +      nagios::service{"ssh_port_host_${name}": +        ensure        => $ensure, +        check_command => "check_ssh_port_host!${real_port}!${check_hostname}" +      } +    } +  } +} diff --git a/puppet/modules/sshd/manifests/openbsd.pp b/puppet/modules/sshd/manifests/openbsd.pp new file mode 100644 index 00000000..cb6dbba6 --- /dev/null +++ b/puppet/modules/sshd/manifests/openbsd.pp @@ -0,0 +1,8 @@ +class sshd::openbsd inherits sshd::base { +  Service[sshd]{ +    restart => '/bin/kill -HUP `/bin/cat /var/run/sshd.pid`', +    stop    => '/bin/kill `/bin/cat /var/run/sshd.pid`', +    start   => '/usr/sbin/sshd', +    status  => '/usr/bin/pgrep -f /usr/sbin/sshd', +  } +} diff --git a/puppet/modules/sshd/manifests/redhat.pp b/puppet/modules/sshd/manifests/redhat.pp new file mode 100644 index 00000000..d7201774 --- /dev/null +++ b/puppet/modules/sshd/manifests/redhat.pp @@ -0,0 +1,5 @@ +class sshd::redhat inherits sshd::linux { +    Package[openssh]{ +        name => 'openssh-server', +    } +} diff --git a/puppet/modules/sshd/manifests/ssh_authorized_key.pp b/puppet/modules/sshd/manifests/ssh_authorized_key.pp new file mode 100644 index 00000000..80cb3b70 --- /dev/null +++ b/puppet/modules/sshd/manifests/ssh_authorized_key.pp @@ -0,0 +1,85 @@ +# wrapper to have some defaults. +define sshd::ssh_authorized_key( +    $ensure = 'present', +    $type = 'ssh-dss', +    $key = 'absent', +    $user = '', +    $target = undef, +    $options = 'absent', +    $override_builtin = undef +){ + +  if ($ensure=='present') and ($key=='absent') { +    fail("You have to set \$key for Sshd::Ssh_authorized_key[${name}]!") +  } + +  $real_user = $user ? { +    false   => $name, +    ''      => $name, +    default => $user, +  } + +  case $target { +    undef,'': { +      case $real_user { +        'root': { $real_target = '/root/.ssh/authorized_keys' } +        default: { $real_target = "/home/${real_user}/.ssh/authorized_keys" } +      } +    } +    default: { +      $real_target = $target +    } +  } + +  # The ssh_authorized_key built-in function (in 2.7.23 at least) +  # will not write an authorized_keys file for a mortal user to +  # a directory they don't have write permission to, puppet attempts to +  # create the file as the user specified with the user parameter and fails. +  # Since ssh will refuse to use authorized_keys files not owned by the +  # user, or in files/directories that allow other users to write, this +  # behavior is deliberate in order to prevent typical non-working +  # configurations. However, it also prevents the case of puppet, running +  # as root, writing a file owned by a mortal user to a common +  # authorized_keys directory such as one might specify in sshd_config with +  # something like +  #  'AuthorizedKeysFile /etc/ssh/authorized_keys/%u' +  # So we provide a way to override the built-in and instead just install +  # via a file resource. There is no additional security risk here, it's +  # nothing a user can't already do by writing their own file resources, +  # we still depend on the filesystem permissions to keep things safe. +  if $override_builtin { +    $header = "# HEADER: This file is managed by Puppet.\n" + +    if $options == 'absent' { +      info("not setting any option for ssh_authorized_key: ${name}") +      $content = "${header}${type} ${key}\n" +    } else { +      $content = "${header}${options} ${type} ${key}\n" +    } + +    file { $real_target: +      ensure  => $ensure, +      content => $content, +      owner   => $real_user, +      mode    => '0600', +    } + +  } else { + +    if $options == 'absent' { +      info("not setting any option for ssh_authorized_key: ${name}") +    } else { +      $real_options = $options +    } + +    ssh_authorized_key{$name: +      ensure  => $ensure, +      type    => $type, +      key     => $key, +      user    => $real_user, +      target  => $real_target, +      options => $real_options, +    } +  } + +} diff --git a/puppet/modules/sshd/manifests/sshkey.pp b/puppet/modules/sshd/manifests/sshkey.pp new file mode 100644 index 00000000..df37a66c --- /dev/null +++ b/puppet/modules/sshd/manifests/sshkey.pp @@ -0,0 +1,21 @@ +# deploys the +class sshd::sshkey { + +  @@sshkey{$::fqdn: +    ensure => present, +    tag    => 'fqdn', +    type   => 'ssh-rsa', +    key    => $::sshrsakey, +  } + +  # In case the node has uses a shared network address, +  # we don't define a sshkey resource using an IP address +  if $sshd::shared_ip == 'no' { +    @@sshkey{$::sshd::sshkey_ipaddress: +      ensure => present, +      tag    => 'ipaddress', +      type   => 'ssh-rsa', +      key    => $::sshrsakey, +    } +  } +} diff --git a/puppet/modules/sshd/spec/classes/client_spec.rb b/puppet/modules/sshd/spec/classes/client_spec.rb new file mode 100644 index 00000000..bd3e35af --- /dev/null +++ b/puppet/modules/sshd/spec/classes/client_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +describe 'sshd::client' do + +  shared_examples "a Linux OS" do +    it { should contain_file('/etc/ssh/ssh_known_hosts').with( +      { +        'ensure'  => 'present', +        'owner'   => 'root', +        'group'   => '0', +        'mode'    => '0644', +      } +    )} +  end + +  context "Debian OS" do +    let :facts do +      { +        :operatingsystem => 'Debian', +        :osfamily        => 'Debian', +        :lsbdistcodename => 'wheezy', +      } +    end +    it_behaves_like "a Linux OS" +    it { should contain_package('openssh-clients').with({ +      'name' => 'openssh-client' +    }) } +  end + +  context "CentOS" do +    it_behaves_like "a Linux OS" do +      let :facts do +        { +        :operatingsystem => 'CentOS', +        :osfamily        => 'RedHat', +        :lsbdistcodename => 'Final', +       } +      end +    end +  end + +end
\ No newline at end of file diff --git a/puppet/modules/sshd/spec/classes/init_spec.rb b/puppet/modules/sshd/spec/classes/init_spec.rb new file mode 100644 index 00000000..e3003d14 --- /dev/null +++ b/puppet/modules/sshd/spec/classes/init_spec.rb @@ -0,0 +1,122 @@ +require 'spec_helper' + +describe 'sshd' do + +  shared_examples "a Linux OS" do +    it { should compile.with_all_deps } +    it { should contain_class('sshd') } +    it { should contain_class('sshd::client') } + +    it { should contain_service('sshd').with({ +      :ensure     => 'running', +      :enable     => true, +      :hasstatus  => true +    })} + +    it { should contain_file('sshd_config').with( +      { +        'ensure'  => 'present', +        'owner'   => 'root', +        'group'   => '0', +        'mode'    => '0600', +      } +    )} + +    context 'change ssh port' do +      let(:params){{ +       :ports => [ 22222], +      }} +      it { should contain_file( +          'sshd_config' +      ).with_content(/Port 22222/)} +    end +  end + +  context "Debian OS" do +    let :facts do +      { +        :operatingsystem => 'Debian', +        :osfamily        => 'Debian', +        :lsbdistcodename => 'wheezy', +      } +    end +    it_behaves_like "a Linux OS" +    it { should contain_package('openssh') } +    it { should contain_class('sshd::debian') } +    it { should contain_service('sshd').with( +      :hasrestart => true +    )} + +    context "Ubuntu" do +      let :facts do +        { +          :operatingsystem => 'Ubuntu', +          :lsbdistcodename => 'precise', +        } +      end +      it_behaves_like "a Linux OS" +      it { should contain_package('openssh') } +      it { should contain_service('sshd').with({ +        :hasrestart => true +      })} +    end +  end + + +#  context "RedHat OS" do +#    it_behaves_like "a Linux OS" do +#      let :facts do +#        { +#          :operatingsystem => 'RedHat', +#          :osfamily        => 'RedHat', +#        } +#      end +#    end +#  end + +  context "CentOS" do +    it_behaves_like "a Linux OS" do +      let :facts do +        { +        :operatingsystem => 'CentOS', +        :osfamily        => 'RedHat', +        :lsbdistcodename => 'Final', +       } +      end +    end +  end + +  context "Gentoo" do +    let :facts do +    { +      :operatingsystem => 'Gentoo', +      :osfamily        => 'Gentoo', +    } +    end +    it_behaves_like "a Linux OS" +    it { should contain_class('sshd::gentoo') } +  end + +  context "OpenBSD" do +    let :facts do +      { +      :operatingsystem => 'OpenBSD', +      :osfamily        => 'OpenBSD', +     } +    end +    it_behaves_like "a Linux OS" +    it { should contain_class('sshd::openbsd') } +  end + +#  context "FreeBSD" do +#    it_behaves_like "a Linux OS" do +#      let :facts do +#        { +#        :operatingsystem => 'FreeBSD', +#        :osfamily        => 'FreeBSD', +#       } +#      end +#    end +#  end + +end
\ No newline at end of file diff --git a/puppet/modules/sshd/spec/defines/ssh_authorized_key_spec.rb b/puppet/modules/sshd/spec/defines/ssh_authorized_key_spec.rb new file mode 100644 index 00000000..c73a91cc --- /dev/null +++ b/puppet/modules/sshd/spec/defines/ssh_authorized_key_spec.rb @@ -0,0 +1,45 @@ +require 'spec_helper' + +describe 'sshd::ssh_authorized_key' do + +  context 'manage authorized key' do +    let(:title) { 'foo' } +    let(:ssh_key) { 'some_secret_ssh_key' } + +    let(:params) {{ +        :key => ssh_key, +    }} + +    it { should contain_ssh_authorized_key('foo').with({ +        'ensure' => 'present', +        'type'   => 'ssh-dss', +        'user'   => 'foo', +        'target' => '/home/foo/.ssh/authorized_keys', +        'key'    => ssh_key, +      }) +    } +  end +  context 'manage authoried key with options' do +    let(:title) { 'foo2' } +    let(:ssh_key) { 'some_secret_ssh_key' } + +    let(:params) {{ +        :key      => ssh_key, +        :options  => ['command="/usr/bin/date"', +                      'no-pty','no-X11-forwarding','no-agent-forwarding', +                      'no-port-forwarding'] +    }} + +    it { should contain_ssh_authorized_key('foo2').with({ +        'ensure'  => 'present', +        'type'    => 'ssh-dss', +        'user'    => 'foo2', +        'target'  => '/home/foo2/.ssh/authorized_keys', +        'key'     => ssh_key, +        'options' => ['command="/usr/bin/date"', +                      'no-pty','no-X11-forwarding','no-agent-forwarding', +                      'no-port-forwarding'] +      }) +    } +  end +end diff --git a/puppet/modules/sshd/spec/functions/ssh_keygen_spec.rb b/puppet/modules/sshd/spec/functions/ssh_keygen_spec.rb new file mode 100644 index 00000000..a6b51173 --- /dev/null +++ b/puppet/modules/sshd/spec/functions/ssh_keygen_spec.rb @@ -0,0 +1,116 @@ +#! /usr/bin/env ruby -S rspec +require 'spec_helper' +require 'rspec-puppet' +require 'mocha' +require 'fileutils' + +describe 'ssh_keygen' do + +  let(:scope) { PuppetlabsSpec::PuppetInternals.scope } + +  it 'should exist' do +    Puppet::Parser::Functions.function("ssh_keygen").should == "function_ssh_keygen" +  end + +  it 'should raise a ParseError if no argument is passed' do +    lambda { +      scope.function_ssh_keygen([]) +    }.should(raise_error(Puppet::ParseError)) +  end + +  it 'should raise a ParseError if there is more than 1 arguments' do +    lambda { +      scope.function_ssh_keygen(["foo", "bar"]) +    }.should( raise_error(Puppet::ParseError)) +  end + +  it 'should raise a ParseError if the argument is not fully qualified' do +    lambda { +      scope.function_ssh_keygen(["foo"]) +    }.should( raise_error(Puppet::ParseError)) +  end + +  it "should raise a ParseError if the private key path is a directory" do +    File.stubs(:directory?).with("/some_dir").returns(true) +    lambda { +      scope.function_ssh_keygen(["/some_dir"]) +    }.should( raise_error(Puppet::ParseError)) +  end + +  it "should raise a ParseError if the public key path is a directory" do +    File.stubs(:directory?).with("/some_dir.pub").returns(true) +    lambda { +      scope.function_ssh_keygen(["/some_dir.pub"]) +    }.should( raise_error(Puppet::ParseError)) +  end + +  describe 'when executing properly' do +    before do +      File.stubs(:directory?).with('/tmp/a/b/c').returns(false) +      File.stubs(:directory?).with('/tmp/a/b/c.pub').returns(false) +      File.stubs(:read).with('/tmp/a/b/c').returns('privatekey') +      File.stubs(:read).with('/tmp/a/b/c.pub').returns('publickey') +    end + +    it 'should fail if the public but not the private key exists' do +      File.stubs(:exists?).with('/tmp/a/b/c').returns(true) +      File.stubs(:exists?).with('/tmp/a/b/c.pub').returns(false) +      lambda { +        scope.function_ssh_keygen(['/tmp/a/b/c']) +      }.should( raise_error(Puppet::ParseError)) +    end + +    it "should fail if the private but not the public key exists" do +      File.stubs(:exists?).with("/tmp/a/b/c").returns(false) +      File.stubs(:exists?).with("/tmp/a/b/c.pub").returns(true) +      lambda { +        scope.function_ssh_keygen(["/tmp/a/b/c"]) +      }.should( raise_error(Puppet::ParseError)) +    end + + +    it "should return an array of size 2 with the right conent if the keyfiles exists" do +      File.stubs(:exists?).with("/tmp/a/b/c").returns(true) +      File.stubs(:exists?).with("/tmp/a/b/c.pub").returns(true) +      File.stubs(:directory?).with('/tmp/a/b').returns(true) +      Puppet::Util.expects(:execute).never +      result = scope.function_ssh_keygen(['/tmp/a/b/c']) +      result.length.should == 2 +      result[0].should == 'privatekey' +      result[1].should == 'publickey' +    end + +    it "should create the directory path if it does not exist" do +      File.stubs(:exists?).with("/tmp/a/b/c").returns(false) +      File.stubs(:exists?).with("/tmp/a/b/c.pub").returns(false) +      File.stubs(:directory?).with("/tmp/a/b").returns(false) +      FileUtils.expects(:mkdir_p).with("/tmp/a/b", :mode => 0700) +      Puppet::Util::Execution.expects(:execute).returns("") +      result = scope.function_ssh_keygen(['/tmp/a/b/c']) +      result.length.should == 2 +      result[0].should == 'privatekey' +      result[1].should == 'publickey' +    end + +    it "should generate the key if the keyfiles do not exist" do +      File.stubs(:exists?).with("/tmp/a/b/c").returns(false) +      File.stubs(:exists?).with("/tmp/a/b/c.pub").returns(false) +      File.stubs(:directory?).with("/tmp/a/b").returns(true) +      Puppet::Util::Execution.expects(:execute).with(['/usr/bin/ssh-keygen','-t', 'rsa', '-b', '4096', '-f', '/tmp/a/b/c', '-P', '', '-q']).returns("") +      result = scope.function_ssh_keygen(['/tmp/a/b/c']) +      result.length.should == 2 +      result[0].should == 'privatekey' +      result[1].should == 'publickey' +    end + +    it "should fail if something goes wrong during generation" do +      File.stubs(:exists?).with("/tmp/a/b/c").returns(false) +      File.stubs(:exists?).with("/tmp/a/b/c.pub").returns(false) +      File.stubs(:directory?).with("/tmp/a/b").returns(true) +      Puppet::Util::Execution.expects(:execute).with(['/usr/bin/ssh-keygen','-t', 'rsa', '-b', '4096', '-f', '/tmp/a/b/c', '-P', '', '-q']).returns("something is wrong") +      lambda { +        scope.function_ssh_keygen(["/tmp/a/b/c"]) +      }.should( raise_error(Puppet::ParseError)) +    end +  end +end diff --git a/puppet/modules/sshd/spec/spec_helper.rb b/puppet/modules/sshd/spec/spec_helper.rb new file mode 100644 index 00000000..b4123fde --- /dev/null +++ b/puppet/modules/sshd/spec/spec_helper.rb @@ -0,0 +1,21 @@ +dir = File.expand_path(File.dirname(__FILE__)) +$LOAD_PATH.unshift File.join(dir, 'lib') +require 'puppet' +require 'rspec' +require 'puppetlabs_spec_helper/module_spec_helper' +#require 'rspec-hiera-puppet' +require 'rspec-puppet/coverage' +require 'rspec/autorun' + +fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures')) + +RSpec.configure do |c| +  c.module_path = File.join(fixture_path, 'modules') +  c.manifest_dir = File.join(fixture_path, 'manifests') +  c.pattern = "spec/*/*_spec.rb" +end + +Puppet::Util::Log.level = :warning +Puppet::Util::Log.newdestination(:console) + +at_exit { RSpec::Puppet::Coverage.report! }
\ No newline at end of file diff --git a/puppet/modules/sshd/spec/spec_helper_system.rb b/puppet/modules/sshd/spec/spec_helper_system.rb new file mode 100644 index 00000000..2c6812fc --- /dev/null +++ b/puppet/modules/sshd/spec/spec_helper_system.rb @@ -0,0 +1,25 @@ +require 'rspec-system/spec_helper' +require 'rspec-system-puppet/helpers' +require 'rspec-system-serverspec/helpers' +include Serverspec::Helper::RSpecSystem +include Serverspec::Helper::DetectOS +include RSpecSystemPuppet::Helpers + +RSpec.configure do |c| +  # Project root +  proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) + +  # Enable colour +  c.tty = true + +  c.include RSpecSystemPuppet::Helpers + +  # This is where we 'setup' the nodes before running our tests +  c.before :suite do +    # Install puppet +    puppet_install +    # Install modules and dependencies +    puppet_module_install(:source => proj_root, :module_name => 'sshd') +    shell('puppet module install puppetlabs-stdlib') +  end +end diff --git a/puppet/modules/sshd/templates/sshd_config/CentOS_5.erb b/puppet/modules/sshd/templates/sshd_config/CentOS_5.erb new file mode 120000 index 00000000..71b767a5 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/CentOS_5.erb @@ -0,0 +1 @@ +CentOS_6.erb
\ No newline at end of file diff --git a/puppet/modules/sshd/templates/sshd_config/CentOS_6.erb b/puppet/modules/sshd/templates/sshd_config/CentOS_6.erb new file mode 100644 index 00000000..4593a91a --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/CentOS_6.erb @@ -0,0 +1,172 @@ +#	$OpenBSD: sshd_config,v 1.73 2005/12/06 22:38:28 reyk Exp $ + +# This is the sshd server system-wide configuration file.  See +# sshd_config(5) for more information. + +# This sshd was compiled with PATH=/usr/local/bin:/bin:/usr/bin + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented.  Uncommented options change a +# default value. + +<% unless (s=scope.lookupvar('::sshd::head_additional_options')).empty? -%> +<%= s %> +<% end -%> + +<% scope.lookupvar('::sshd::ports').to_a.each do |port| -%> +<% if port == 'off' -%> +#Port -- disabled by puppet +<% else -%> +Port <%= port %> +<% end -%> +<% end -%> + +# Use these options to restrict which interfaces/protocols sshd will bind to +<% scope.lookupvar('::sshd::listen_address').to_a.each do |address| -%> +ListenAddress <%= address %> +<% end -%> + +# Disable legacy (protocol version 1) support in the server for new +# installations. In future the default will change to require explicit +# activation of protocol 1 +Protocol 2 + +# HostKey for protocol version 1 +#HostKey /etc/ssh/ssh_host_key +# HostKeys for protocol version 2 +#HostKey /etc/ssh/ssh_host_rsa_key +#HostKey /etc/ssh/ssh_host_dsa_key + +# Lifetime and size of ephemeral version 1 server key +#KeyRegenerationInterval 1h +#ServerKeyBits 1024 + +# Logging +# obsoletes QuietMode and FascistLogging +#SyslogFacility AUTH +SyslogFacility AUTHPRIV +#LogLevel INFO + +# Authentication: + +#LoginGraceTime 2m +PermitRootLogin <%= scope.lookupvar('::sshd::permit_root_login') %> + +StrictModes <%= scope.lookupvar('::sshd::strict_modes') %> + +#MaxAuthTries 6 + +RSAAuthentication <%= scope.lookupvar('::sshd::rsa_authentication') %> +PubkeyAuthentication <%= scope.lookupvar('::sshd::pubkey_authentication') %> +AuthorizedKeysFile <%= scope.lookupvar('::sshd::authorized_keys_file') %> +#AuthorizedKeysCommand none +#AuthorizedKeysCommandRunAs nobody + +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +RhostsRSAAuthentication <%= scope.lookupvar('::sshd::rhosts_rsa_authentication') %> + +# similar for protocol version 2 +HostbasedAuthentication <%= scope.lookupvar('::sshd::hostbased_authentication') %> + +# Change to yes if you don't trust ~/.ssh/known_hosts for +# RhostsRSAAuthentication and HostbasedAuthentication +#IgnoreUserKnownHosts no + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts <%= scope.lookupvar('::sshd::ignore_rhosts') %> + +# To disable tunneled clear text passwords, change to no here! +PasswordAuthentication <%= scope.lookupvar('::sshd::password_authentication') %> + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords <%= scope.lookupvar('::sshd::permit_empty_passwords') %> + +# Change to no to disable s/key passwords +ChallengeResponseAuthentication <%= scope.lookupvar('::sshd::challenge_response_authentication') %> + +# Kerberos options +#KerberosAuthentication no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes +#KerberosGetAFSToken no +#KerberosUseKuserok yes + +# GSSAPI options +#GSSAPIAuthentication no +#GSSAPICleanupCredentials yes + +# Set this to 'yes' to enable PAM authentication, account processing,  +# and session processing. If this is enabled, PAM authentication will  +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication.  Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +#UsePAM no +UsePAM <%= scope.lookupvar('::sshd::use_pam') %> + +# Accept locale-related environment variables +AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES +AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT +AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE +AcceptEnv XMODIFIERS + +#AllowAgentForwarding yes +AllowTcpForwarding <%= scope.lookupvar('::sshd::tcp_forwarding') %> +#GatewayPorts no +#X11Forwarding no +X11Forwarding <%= scope.lookupvar('::sshd::x11_forwarding') %> +#X11DisplayOffset 10 +#X11UseLocalhost yes +PrintMotd <%= scope.lookupvar('::sshd::print_motd') %> +#PrintLastLog yes +#TCPKeepAlive yes +#UseLogin no +#UsePrivilegeSeparation yes +#PermitUserEnvironment no +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#ShowPatchLevel no +#UseDNS yes +#PidFile /var/run/sshd.pid +#MaxStartups 10:30:100 +#PermitTunnel no +#ChrootDirectory none + +# no default banner path +#Banner /some/path + +# override default of no subsystems +Subsystem      sftp    <%= (s=scope.lookupvar('::sshd::sftp_subsystem')).empty? ? '/usr/libexec/openssh/sftp-server' : s %>  + +<% unless (s=scope.lookupvar('::sshd::allowed_users')).empty? -%> +AllowUsers <%= s %> +<% end -%> +<% unless (s=scope.lookupvar('::sshd::allowed_groups')).empty? -%> +AllowGroups <%= s %> +<%- end -%> + +<% if scope.lookupvar('::sshd::hardened') == 'yes' -%> +<% if (scope.function_versioncmp([scope.lookupvar('::ssh_version'),'6.5'])) >= 0 -%> +KexAlgorithms curve25519-sha256@libssh.org +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com +<% else -%> +Ciphers aes256-ctr +MACs hmac-sha1 +<% end -%> +<% end -%> + +# Example of overriding settings on a per-user basis +#Match User anoncvs +#      X11Forwarding no +#      AllowTcpForwarding no +#      ForceCommand cvs server +# +<% unless (s=scope.lookupvar('::sshd::tail_additional_options')).empty? -%> +<%= s %> +<% end -%> diff --git a/puppet/modules/sshd/templates/sshd_config/CentOS_7.erb b/puppet/modules/sshd/templates/sshd_config/CentOS_7.erb new file mode 100644 index 00000000..f55fb9d0 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/CentOS_7.erb @@ -0,0 +1,186 @@ +# $OpenBSD: sshd_config,v 1.90 2013/05/16 04:09:14 dtucker Exp $ + +# This is the sshd server system-wide configuration file.  See +# sshd_config(5) for more information. + +# This sshd was compiled with PATH=/usr/local/bin:/bin:/usr/bin + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented.  Uncommented options change a +# default value. + +<% unless (s=scope.lookupvar('::sshd::head_additional_options')).empty? -%> +<%= s %> +<% end -%> + +# If you want to change the port on a SELinux system, you have to tell +# SELinux about this change. +# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER +# +<% scope.lookupvar('::sshd::ports').to_a.each do |port| -%> +<% if port == 'off' -%> +#Port -- disabled by puppet +<% else -%> +Port <%= port %> +<% end -%> +<% end -%> +<% scope.lookupvar('::sshd::listen_address').to_a.each do |address| -%> +ListenAddress <%= address %> +<% end -%> + +# The default requires explicit activation of protocol 1 +#Protocol 2 + +# HostKey for protocol version 1 +#HostKey /etc/ssh/ssh_host_key +# HostKeys for protocol version 2 +<% scope.lookupvar('::sshd::hostkey_type').to_a.each do |hostkey_type| -%> +HostKey /etc/ssh/ssh_host_<%=hostkey_type %>_key +<% end -%> + +# Lifetime and size of ephemeral version 1 server key +#KeyRegenerationInterval 1h +#ServerKeyBits 1024 + +# Ciphers and keying +#RekeyLimit default none + +# Logging +# obsoletes QuietMode and FascistLogging +#SyslogFacility AUTH +SyslogFacility AUTHPRIV +#LogLevel INFO + +# Authentication: + +#LoginGraceTime 2m +PermitRootLogin <%= scope.lookupvar('::sshd::permit_root_login') %> +StrictModes <%= scope.lookupvar('::sshd::strict_modes') %> +#MaxAuthTries 6 +#MaxSessions 10 + +RSAAuthentication <%= scope.lookupvar('::sshd::rsa_authentication') %> +PubkeyAuthentication <%= scope.lookupvar('::sshd::pubkey_authentication') %> +AuthorizedKeysFile <%= scope.lookupvar('::sshd::authorized_keys_file') %> +#AuthorizedPrincipalsFile none +#AuthorizedKeysCommand none +#AuthorizedKeysCommandRunAs nobody + +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +RhostsRSAAuthentication <%= scope.lookupvar('::sshd::rhosts_rsa_authentication') %> + +# similar for protocol version 2 +HostbasedAuthentication <%= scope.lookupvar('::sshd::hostbased_authentication') %> + +# Change to yes if you don't trust ~/.ssh/known_hosts for +# RhostsRSAAuthentication and HostbasedAuthentication +#IgnoreUserKnownHosts no + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts <%= scope.lookupvar('::sshd::ignore_rhosts') %> + +# To disable tunneled clear text passwords, change to no here! +PasswordAuthentication <%= scope.lookupvar('::sshd::password_authentication') %> + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords <%= scope.lookupvar('::sshd::permit_empty_passwords') %> + +# Change to no to disable s/key passwords +ChallengeResponseAuthentication <%= scope.lookupvar('::sshd::challenge_response_authentication') %> + +# Kerberos options +#KerberosAuthentication no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes +#KerberosGetAFSToken no +#KerberosUseKuserok yes + +# GSSAPI options +GSSAPIAuthentication no +GSSAPICleanupCredentials yes +#GSSAPIStrictAcceptorCheck yes +#GSSAPIKeyExchange no + +# Set this to 'yes' to enable PAM authentication, account processing,  +# and session processing. If this is enabled, PAM authentication will  +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication.  Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several +# problems. +#UsePAM no +UsePAM <%= scope.lookupvar('::sshd::use_pam') %> + +#AllowAgentForwarding yes +AllowTcpForwarding <%= scope.lookupvar('::sshd::tcp_forwarding') %> +#GatewayPorts no +#X11Forwarding no +X11Forwarding <%= scope.lookupvar('::sshd::x11_forwarding') %> +#X11DisplayOffset 10 +#X11UseLocalhost yes +PrintMotd <%= scope.lookupvar('::sshd::print_motd') %> +#PrintLastLog yes +#TCPKeepAlive yes +#UseLogin no +UsePrivilegeSeparation sandbox    # Default for new installations. +#PermitUserEnvironment no +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#ShowPatchLevel no +#UseDNS yes +#PidFile /var/run/sshd.pid +#MaxStartups 10:30:100 +#PermitTunnel no +#ChrootDirectory none +#VersionAddendum none + +# no default banner path +#Banner none + +# Accept locale-related environment variables +AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES +AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT +AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE +AcceptEnv XMODIFIERS + + +# override default of no subsystems +Subsystem sftp  <%= (s=scope.lookupvar('::sshd::sftp_subsystem')).empty? ? '/usr/libexec/openssh/sftp-server' : s %>  + +<% unless (s=scope.lookupvar('::sshd::allowed_users')).empty? -%> +AllowUsers <%= s %> +<% end -%> +<% unless (s=scope.lookupvar('::sshd::allowed_groups')).empty? -%> +AllowGroups <%= s %> +<%- end -%> + +# Uncomment this if you want to use .local domain +#Host *.local +#  CheckHostIP no + +<% if scope.lookupvar('::sshd::hardened') == 'yes' -%> +<% if (scope.function_versioncmp([scope.lookupvar('::ssh_version'),'6.5'])) >= 0 -%> +KexAlgorithms curve25519-sha256@libssh.org +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com +<% else -%> +Ciphers aes256-ctr +MACs hmac-sha1 +<% end -%> +<% end -%> + +# Example of overriding settings on a per-user basis +#Match User anoncvs +# X11Forwarding no +# AllowTcpForwarding no +# ForceCommand cvs server + +<% unless (s=scope.lookupvar('::sshd::tail_additional_options')).empty? -%> +<%= s %> +<% end -%> diff --git a/puppet/modules/sshd/templates/sshd_config/Debian_jessie.erb b/puppet/modules/sshd/templates/sshd_config/Debian_jessie.erb new file mode 100644 index 00000000..91dbfff0 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/Debian_jessie.erb @@ -0,0 +1,124 @@ +# This file is managed by Puppet, all local modifications will be overwritten +# +# Package generated configuration file +# See the sshd_config(5) manpage for details + +<% unless (s=scope.lookupvar('::sshd::head_additional_options')).empty? -%> +<%= s %> +<% end -%> + +# What ports, IPs and protocols we listen for +<% scope.lookupvar('::sshd::ports').to_a.each do |port| -%> +<% if port == 'off' -%> +#Port -- disabled by puppet +<% else -%> +Port <%= port %> +<% end -%> +<% end -%> + +# Use these options to restrict which interfaces/protocols sshd will bind to +<% scope.lookupvar('::sshd::listen_address').to_a.each do |address| -%> +ListenAddress <%= address %> +<% end -%> +Protocol 2 +# HostKeys for protocol version 2 +<% scope.lookupvar('::sshd::hostkey_type').to_a.each do |hostkey_type| -%> +HostKey /etc/ssh/ssh_host_<%=hostkey_type %>_key +<% end -%> +#Privilege Separation is turned on for security +UsePrivilegeSeparation yes + +# Lifetime and size of ephemeral version 1 server key +KeyRegenerationInterval 3600 +ServerKeyBits 1024 + +# Logging +SyslogFacility AUTH +LogLevel INFO + +# Authentication: +LoginGraceTime 120 +PermitRootLogin <%= scope.lookupvar('::sshd::permit_root_login') %> +StrictModes <%= scope.lookupvar('::sshd::strict_modes') %> + +RSAAuthentication <%= scope.lookupvar('::sshd::rsa_authentication') %> +PubkeyAuthentication <%= scope.lookupvar('::sshd::pubkey_authentication') %> +AuthorizedKeysFile <%= scope.lookupvar('::sshd::authorized_keys_file') %> + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts <%= scope.lookupvar('::sshd::ignore_rhosts') %> +# For this to work you will also need host keys in /etc/ssh_known_hosts +RhostsRSAAuthentication <%= scope.lookupvar('::sshd::rhosts_rsa_authentication') %> +# similar for protocol version 2 +HostbasedAuthentication <%= scope.lookupvar('::sshd::hostbased_authentication') %> +# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication +#IgnoreUserKnownHosts yes + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords <%= scope.lookupvar('::sshd::permit_empty_passwords') %> + +# Change to yes to enable challenge-response passwords (beware issues with +# some PAM modules and threads) +ChallengeResponseAuthentication <%= scope.lookupvar('::sshd::challenge_response_authentication') %> + +# Change to no to disable tunnelled clear text passwords +PasswordAuthentication <%= scope.lookupvar('::sshd::password_authentication') %> + +# Kerberos options +KerberosAuthentication <%= scope.lookupvar('::sshd::kerberos_authentication') %> +#KerberosGetAFSToken no +KerberosOrLocalPasswd <%= scope.lookupvar('::sshd::kerberos_orlocalpasswd') %> +KerberosTicketCleanup <%= scope.lookupvar('::sshd::kerberos_ticketcleanup') %> + +# GSSAPI options +GSSAPIAuthentication <%= scope.lookupvar('::sshd::gssapi_authentication') %> +GSSAPICleanupCredentials <%= scope.lookupvar('::sshd::gssapi_cleanupcredentials') %> + +X11Forwarding <%= scope.lookupvar('::sshd::x11_forwarding') %> +X11DisplayOffset 10 +PrintMotd <%= scope.lookupvar('::sshd::print_motd') %> +PrintLastLog yes +TCPKeepAlive yes +#UseLogin no + +#MaxStartups 10:30:60 +#Banner /etc/issue.net +# do not reveal debian version (default is yes) +DebianBanner no + +# Allow client to pass locale environment variables +AcceptEnv LANG LC_* + +Subsystem      sftp    <%= (s=scope.lookupvar('::sshd::sftp_subsystem')).empty? ? '/usr/lib/openssh/sftp-server' : s %> + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication.  Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM <%= scope.lookupvar('::sshd::use_pam') %> + +AllowTcpForwarding <%= scope.lookupvar('::sshd::tcp_forwarding') %> + +AllowAgentForwarding <%= scope.lookupvar('::sshd::agent_forwarding') %> + +<% unless (s=scope.lookupvar('::sshd::allowed_users')).empty? -%> +AllowUsers <%= s %> +<% end -%> +<% unless (s=scope.lookupvar('::sshd::allowed_groups')).empty? -%> +AllowGroups <%= s %> +<%- end -%> + +<% if scope.lookupvar('::sshd::hardened') == 'yes' -%> +KexAlgorithms curve25519-sha256@libssh.org +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com +<% end -%> + +<% unless (s=scope.lookupvar('::sshd::tail_additional_options')).empty? -%> +<%= s %> +<% end -%> diff --git a/puppet/modules/sshd/templates/sshd_config/Debian_sid.erb b/puppet/modules/sshd/templates/sshd_config/Debian_sid.erb new file mode 100644 index 00000000..91dbfff0 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/Debian_sid.erb @@ -0,0 +1,124 @@ +# This file is managed by Puppet, all local modifications will be overwritten +# +# Package generated configuration file +# See the sshd_config(5) manpage for details + +<% unless (s=scope.lookupvar('::sshd::head_additional_options')).empty? -%> +<%= s %> +<% end -%> + +# What ports, IPs and protocols we listen for +<% scope.lookupvar('::sshd::ports').to_a.each do |port| -%> +<% if port == 'off' -%> +#Port -- disabled by puppet +<% else -%> +Port <%= port %> +<% end -%> +<% end -%> + +# Use these options to restrict which interfaces/protocols sshd will bind to +<% scope.lookupvar('::sshd::listen_address').to_a.each do |address| -%> +ListenAddress <%= address %> +<% end -%> +Protocol 2 +# HostKeys for protocol version 2 +<% scope.lookupvar('::sshd::hostkey_type').to_a.each do |hostkey_type| -%> +HostKey /etc/ssh/ssh_host_<%=hostkey_type %>_key +<% end -%> +#Privilege Separation is turned on for security +UsePrivilegeSeparation yes + +# Lifetime and size of ephemeral version 1 server key +KeyRegenerationInterval 3600 +ServerKeyBits 1024 + +# Logging +SyslogFacility AUTH +LogLevel INFO + +# Authentication: +LoginGraceTime 120 +PermitRootLogin <%= scope.lookupvar('::sshd::permit_root_login') %> +StrictModes <%= scope.lookupvar('::sshd::strict_modes') %> + +RSAAuthentication <%= scope.lookupvar('::sshd::rsa_authentication') %> +PubkeyAuthentication <%= scope.lookupvar('::sshd::pubkey_authentication') %> +AuthorizedKeysFile <%= scope.lookupvar('::sshd::authorized_keys_file') %> + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts <%= scope.lookupvar('::sshd::ignore_rhosts') %> +# For this to work you will also need host keys in /etc/ssh_known_hosts +RhostsRSAAuthentication <%= scope.lookupvar('::sshd::rhosts_rsa_authentication') %> +# similar for protocol version 2 +HostbasedAuthentication <%= scope.lookupvar('::sshd::hostbased_authentication') %> +# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication +#IgnoreUserKnownHosts yes + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords <%= scope.lookupvar('::sshd::permit_empty_passwords') %> + +# Change to yes to enable challenge-response passwords (beware issues with +# some PAM modules and threads) +ChallengeResponseAuthentication <%= scope.lookupvar('::sshd::challenge_response_authentication') %> + +# Change to no to disable tunnelled clear text passwords +PasswordAuthentication <%= scope.lookupvar('::sshd::password_authentication') %> + +# Kerberos options +KerberosAuthentication <%= scope.lookupvar('::sshd::kerberos_authentication') %> +#KerberosGetAFSToken no +KerberosOrLocalPasswd <%= scope.lookupvar('::sshd::kerberos_orlocalpasswd') %> +KerberosTicketCleanup <%= scope.lookupvar('::sshd::kerberos_ticketcleanup') %> + +# GSSAPI options +GSSAPIAuthentication <%= scope.lookupvar('::sshd::gssapi_authentication') %> +GSSAPICleanupCredentials <%= scope.lookupvar('::sshd::gssapi_cleanupcredentials') %> + +X11Forwarding <%= scope.lookupvar('::sshd::x11_forwarding') %> +X11DisplayOffset 10 +PrintMotd <%= scope.lookupvar('::sshd::print_motd') %> +PrintLastLog yes +TCPKeepAlive yes +#UseLogin no + +#MaxStartups 10:30:60 +#Banner /etc/issue.net +# do not reveal debian version (default is yes) +DebianBanner no + +# Allow client to pass locale environment variables +AcceptEnv LANG LC_* + +Subsystem      sftp    <%= (s=scope.lookupvar('::sshd::sftp_subsystem')).empty? ? '/usr/lib/openssh/sftp-server' : s %> + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication.  Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM <%= scope.lookupvar('::sshd::use_pam') %> + +AllowTcpForwarding <%= scope.lookupvar('::sshd::tcp_forwarding') %> + +AllowAgentForwarding <%= scope.lookupvar('::sshd::agent_forwarding') %> + +<% unless (s=scope.lookupvar('::sshd::allowed_users')).empty? -%> +AllowUsers <%= s %> +<% end -%> +<% unless (s=scope.lookupvar('::sshd::allowed_groups')).empty? -%> +AllowGroups <%= s %> +<%- end -%> + +<% if scope.lookupvar('::sshd::hardened') == 'yes' -%> +KexAlgorithms curve25519-sha256@libssh.org +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com +<% end -%> + +<% unless (s=scope.lookupvar('::sshd::tail_additional_options')).empty? -%> +<%= s %> +<% end -%> diff --git a/puppet/modules/sshd/templates/sshd_config/Debian_squeeze.erb b/puppet/modules/sshd/templates/sshd_config/Debian_squeeze.erb new file mode 100644 index 00000000..649b320a --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/Debian_squeeze.erb @@ -0,0 +1,127 @@ +# This file is managed by Puppet, all local modifications will be overwritten +# +# Package generated configuration file +# See the sshd(8) manpage for details + +<% unless (s=scope.lookupvar('::sshd::head_additional_options')).empty? -%> +<%= s %> +<% end -%> + +# What ports, IPs and protocols we listen for +<% scope.lookupvar('::sshd::ports').to_a.each do |port| -%> +<% if port == 'off' -%> +#Port -- disabled by puppet +<% else -%> +Port <%= port %> +<% end -%> +<% end -%> + +# Use these options to restrict which interfaces/protocols sshd will bind to +<% scope.lookupvar('::sshd::listen_address').to_a.each do |address| -%> +ListenAddress <%= address %> +<% end -%> +Protocol 2 +# HostKeys for protocol version 2 +<% scope.lookupvar('::sshd::hostkey_type').to_a.each do |hostkey_type| -%> +HostKey /etc/ssh/ssh_host_<%=hostkey_type %>_key +<% end -%> + +#Privilege Separation is turned on for security +UsePrivilegeSeparation yes + +# Lifetime and size of ephemeral version 1 server key +KeyRegenerationInterval 3600 +ServerKeyBits 768 + +# Logging +SyslogFacility AUTH +LogLevel INFO + +# Authentication: +LoginGraceTime 120 +PermitRootLogin <%= scope.lookupvar('::sshd::permit_root_login') %> + +StrictModes <%= scope.lookupvar('::sshd::strict_modes') %> + +RSAAuthentication <%= scope.lookupvar('::sshd::rsa_authentication') %> + +PubkeyAuthentication <%= scope.lookupvar('::sshd::pubkey_authentication') %> + +AuthorizedKeysFile <%= scope.lookupvar('::sshd::authorized_keys_file') %> + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts <%= scope.lookupvar('::sshd::ignore_rhosts') %> +# For this to work you will also need host keys in /etc/ssh_known_hosts +RhostsRSAAuthentication <%= scope.lookupvar('::sshd::rhosts_rsa_authentication') %> +# similar for protocol version 2 +HostbasedAuthentication <%= scope.lookupvar('::sshd::hostbased_authentication') %> +# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication +#IgnoreUserKnownHosts yes + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords <%= scope.lookupvar('::sshd::permit_empty_passwords') %> + +# Change to yes to enable challenge-response passwords (beware issues with +# some PAM modules and threads) +ChallengeResponseAuthentication <%= scope.lookupvar('::sshd::challenge_response_authentication') %> + +# To disable tunneled clear text passwords, change to no here! +PasswordAuthentication <%= scope.lookupvar('::sshd::password_authentication') %> + +# Kerberos options +KerberosAuthentication <%= scope.lookupvar('::sshd::kerberos_authentication') %> +KerberosOrLocalPasswd <%= scope.lookupvar('::sshd::kerberos_orlocalpasswd') %> +KerberosTicketCleanup <%= scope.lookupvar('::sshd::kerberos_ticketcleanup') %> + +# GSSAPI options +GSSAPIAuthentication <%= scope.lookupvar('::sshd::gssapi_authentication') %> +GSSAPICleanupCredentials <%= scope.lookupvar('::sshd::gssapi_cleanupcredentials') %> + +X11Forwarding <%= scope.lookupvar('::sshd::x11_forwarding') %> +X11DisplayOffset 10 +PrintMotd <%= scope.lookupvar('::sshd::print_motd') %> +PrintLastLog yes +TCPKeepAlive yes + +#UseLogin no + +#MaxStartups 10:30:60 +#Banner /etc/issue.net +# do not reveal debian version (default is yes) +DebianBanner no + +# Allow client to pass locale environment variables +AcceptEnv LANG LC_* + +Subsystem      sftp    <%= (s=scope.lookupvar('::sshd::sftp_subsystem')).empty? ? '/usr/lib/openssh/sftp-server' : s %> + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication.  Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM <%= scope.lookupvar('::sshd::use_pam') %> + +AllowTcpForwarding <%= scope.lookupvar('::sshd::tcp_forwarding') %> + +AllowAgentForwarding <%= scope.lookupvar('::sshd::agent_forwarding') %> + +<% unless (s=scope.lookupvar('::sshd::allowed_users')).empty? -%> +AllowUsers <%= s %> +<% end -%> +<% unless (s=scope.lookupvar('::sshd::allowed_groups')).empty? -%> +AllowGroups <%= s %> +<%- end -%> + +<% if scope.lookupvar('::sshd::hardened') == 'yes' -%> +Ciphers aes256-ctr +MACs hmac-sha2-512 +<% end -%> + +<% unless (s=scope.lookupvar('::sshd::tail_additional_options')).empty? -%> +<%= s %> +<% end -%> diff --git a/puppet/modules/sshd/templates/sshd_config/Debian_wheezy.erb b/puppet/modules/sshd/templates/sshd_config/Debian_wheezy.erb new file mode 100644 index 00000000..bcb15286 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/Debian_wheezy.erb @@ -0,0 +1,132 @@ +# This file is managed by Puppet, all local modifications will be overwritten +# +# Package generated configuration file +# See the sshd(8) manpage for details + +<% unless (s=scope.lookupvar('::sshd::head_additional_options')).empty? -%> +<%= s %> +<% end -%> + +# What ports, IPs and protocols we listen for +<% scope.lookupvar('::sshd::ports').to_a.each do |port| -%> +<% if port == 'off' -%> +#Port -- disabled by puppet +<% else -%> +Port <%= port %> +<% end -%> +<% end -%> + +# Use these options to restrict which interfaces/protocols sshd will bind to +<% scope.lookupvar('::sshd::listen_address').to_a.each do |address| -%> +ListenAddress <%= address %> +<% end -%> +Protocol 2 +# HostKeys for protocol version 2 +<% scope.lookupvar('::sshd::hostkey_type').to_a.each do |hostkey_type| -%> +HostKey /etc/ssh/ssh_host_<%=hostkey_type %>_key +<% end -%> +#Privilege Separation is turned on for security +UsePrivilegeSeparation yes + +# Lifetime and size of ephemeral version 1 server key +KeyRegenerationInterval 3600 +ServerKeyBits 768 + +# Logging +SyslogFacility AUTH +LogLevel INFO + +# Authentication: +LoginGraceTime 120 +PermitRootLogin <%= scope.lookupvar('::sshd::permit_root_login') %> + +StrictModes <%= scope.lookupvar('::sshd::strict_modes') %> + +RSAAuthentication <%= scope.lookupvar('::sshd::rsa_authentication') %> + +PubkeyAuthentication <%= scope.lookupvar('::sshd::pubkey_authentication') %> + +AuthorizedKeysFile <%= scope.lookupvar('::sshd::authorized_keys_file') %> + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts <%= scope.lookupvar('::sshd::ignore_rhosts') %> +# For this to work you will also need host keys in /etc/ssh_known_hosts +RhostsRSAAuthentication <%= scope.lookupvar('::sshd::rhosts_rsa_authentication') %> +# similar for protocol version 2 +HostbasedAuthentication <%= scope.lookupvar('::sshd::hostbased_authentication') %> +# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication +#IgnoreUserKnownHosts yes + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords <%= scope.lookupvar('::sshd::permit_empty_passwords') %> + +# Change to yes to enable challenge-response passwords (beware issues with +# some PAM modules and threads) +ChallengeResponseAuthentication <%= scope.lookupvar('::sshd::challenge_response_authentication') %> + +# To disable tunneled clear text passwords, change to no here! +PasswordAuthentication <%= scope.lookupvar('::sshd::password_authentication') %> + +# Kerberos options +KerberosAuthentication <%= scope.lookupvar('::sshd::kerberos_authentication') %> +KerberosOrLocalPasswd <%= scope.lookupvar('::sshd::kerberos_orlocalpasswd') %> +KerberosTicketCleanup <%= scope.lookupvar('::sshd::kerberos_ticketcleanup') %> + +# GSSAPI options +GSSAPIAuthentication <%= scope.lookupvar('::sshd::gssapi_authentication') %> +GSSAPICleanupCredentials <%= scope.lookupvar('::sshd::gssapi_cleanupcredentials') %> + +X11Forwarding <%= scope.lookupvar('::sshd::x11_forwarding') %> +X11DisplayOffset 10 +PrintMotd <%= scope.lookupvar('::sshd::print_motd') %> +PrintLastLog yes +TCPKeepAlive yes + +#UseLogin no + +#MaxStartups 10:30:60 +#Banner /etc/issue.net +# do not reveal debian version (default is yes) +DebianBanner no + +# Allow client to pass locale environment variables +AcceptEnv LANG LC_* + +Subsystem      sftp    <%= (s=scope.lookupvar('::sshd::sftp_subsystem')).empty? ? '/usr/lib/openssh/sftp-server' : s %> + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication.  Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM <%= scope.lookupvar('::sshd::use_pam') %> + +AllowTcpForwarding <%= scope.lookupvar('::sshd::tcp_forwarding') %> + +AllowAgentForwarding <%= scope.lookupvar('::sshd::agent_forwarding') %> + +<% unless (s=scope.lookupvar('::sshd::allowed_users')).empty? -%> +AllowUsers <%= s %> +<% end -%> +<% unless (s=scope.lookupvar('::sshd::allowed_groups')).empty? -%> +AllowGroups <%= s %> +<%- end -%> + +<% if scope.lookupvar('::sshd::hardened') == 'yes' -%> +<% if (scope.function_versioncmp([scope.lookupvar('::ssh_version'),'6.5'])) >= 0 -%> +KexAlgorithms curve25519-sha256@libssh.org +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com +<% else -%> +Ciphers aes256-ctr +MACs hmac-sha2-512 +<% end -%> +<% end -%> + +<% unless (s=scope.lookupvar('::sshd::tail_additional_options')).empty? -%> +<%= s %> +<% end -%> diff --git a/puppet/modules/sshd/templates/sshd_config/FreeBSD.erb b/puppet/modules/sshd/templates/sshd_config/FreeBSD.erb new file mode 100644 index 00000000..5298ade9 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/FreeBSD.erb @@ -0,0 +1,168 @@ +#	$OpenBSD: sshd_config,v 1.81 2009/10/08 14:03:41 markus Exp $ +#	$FreeBSD: src/crypto/openssh/sshd_config,v 1.49.2.2.2.1 2010/06/14 02:09:06 kensmith Exp $ + +# This is the sshd server system-wide configuration file.  See +# sshd_config(5) for more information. + +# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented.  Uncommented options change a +# default value. + +# Note that some of FreeBSD's defaults differ from OpenBSD's, and +# FreeBSD has a few additional options. + +#VersionAddendum FreeBSD-20100308 + +<% unless (s=scope.lookupvar('::sshd::head_additional_options')).empty? -%> +<%= s %> +<% end -%> + +# What ports, IPs and protocols we listen for +<% scope.lookupvar('::sshd::ports').to_a.each do |port| -%> +<% if port == 'off' -%> +#Port -- disabled by puppet +<% else -%> +Port <%= port %> +<% end -%> +<% end -%> + +#AddressFamily any +<% scope.lookupvar('::sshd::listen_address').to_a.each do |address| -%> +ListenAddress <%= address %> +<% end -%> + +# The default requires explicit activation of protocol 1 +Protocol 2 + +# HostKey for protocol version 1 +#HostKey /etc/ssh/ssh_host_key +# HostKeys for protocol version 2 +<% scope.lookupvar('::sshd::hostkey_type').to_a.each do |hostkey_type| -%> +HostKey /etc/ssh/ssh_host_<%=hostkey_type %>_key +<% end -%> + +# Lifetime and size of ephemeral version 1 server key +#KeyRegenerationInterval 1h +#ServerKeyBits 1024 + +# Logging +# obsoletes QuietMode and FascistLogging +SyslogFacility AUTH +LogLevel INFO + +# Authentication: + +LoginGraceTime 600 +PermitRootLogin <%= scope.lookupvar('::sshd::permit_root_login') %> + +StrictModes <%= scope.lookupvar('::sshd::strict_modes') %> + +#MaxAuthTries 6 +#MaxSessions 10 + +RSAAuthentication <%= scope.lookupvar('::sshd::rsa_authentication') %> + +PubkeyAuthentication <%= scope.lookupvar('::sshd::pubkey_authentication') %> + +AuthorizedKeysFile <%= scope.lookupvar('::sshd::authorized_keys_file') %> + +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +RhostsRSAAuthentication <%= scope.lookupvar('::sshd::rhosts_rsa_authentication') %> + +# similar for protocol version 2 +HostbasedAuthentication <%= scope.lookupvar('::sshd::hostbased_authentication') %> + +# Change to yes if you don't trust ~/.ssh/known_hosts for +# RhostsRSAAuthentication and HostbasedAuthentication +#IgnoreUserKnownHosts no +# Don't read the user's ~/.rhosts and ~/.shosts files +#IgnoreRhosts yes + +# Change to yes to enable built-in password authentication. +PasswordAuthentication <%= scope.lookupvar('::sshd::password_authentication') %> + +PermitEmptyPasswords <%= scope.lookupvar('::sshd::permit_empty_passwords') %> + +# Change to no to disable PAM authentication +ChallengeResponseAuthentication <%= scope.lookupvar('::sshd::challenge_response_authentication') %> + +# Kerberos options +KerberosAuthentication <%= scope.lookupvar('::sshd::kerberos_authentication') %> +KerberosOrLocalPasswd <%= scope.lookupvar('::sshd::kerberos_orlocalpasswd') %> +KerberosTicketCleanup <%= scope.lookupvar('::sshd::kerberos_ticketcleanup') %> + +# GSSAPI options +GSSAPIAuthentication <%= scope.lookupvar('::sshd::gssapi_authentication') %> +GSSAPICleanupCredentials <%= scope.lookupvar('::sshd::gssapi_cleanupcredentials') %> + +# Set this to 'no' to disable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will  +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication.  Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM <%= scope.lookupvar('::sshd::use_pam') %> + +AllowAgentForwarding <%= scope.lookupvar('::sshd::agent_forwarding') %> + +AllowTcpForwarding <%= scope.lookupvar('::sshd::tcp_forwarding') %> + +#GatewayPorts no +X11Forwarding <%= scope.lookupvar('::sshd::x11_forwarding') %> + +X11DisplayOffset 10 +#X11UseLocalhost yes +PrintMotd <%= sshd_print_motd %> +#PrintLastLog yes +TCPKeepAlive yes +#UseLogin no +#UsePrivilegeSeparation yes +#PermitUserEnvironment no +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#UseDNS yes +#PidFile /var/run/sshd.pid +#MaxStartups 10 +#PermitTunnel no +#ChrootDirectory none + +# no default banner path +#Banner none + +# override default of no subsystems +Subsystem      sftp    <%= (s=scope.lookupvar('::sshd::sftp_subsystem')).empty? ? '/usr/libexec/sftp-server' : s %> + +# Example of overriding settings on a per-user basis +#Match User anoncvs +#	X11Forwarding no +#	AllowTcpForwarding no +#	ForceCommand cvs server + +<% unless (s=scope.lookupvar('::sshd::allowed_users')).empty? -%> +AllowUsers <%= s %> +<% end -%> +<% unless (s=scope.lookupvar('::sshd::allowed_groups')).empty? -%> +AllowGroups <%= s %> +<%- end -%> + +<% if scope.lookupvar('::sshd::hardened') == 'yes' -%> +<% if (scope.function_versioncmp([scope.lookupvar('::ssh_version'),'6.5'])) >= 0 -%> +KexAlgorithms curve25519-sha256@libssh.org +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com +<% else -%> +Ciphers aes256-ctr +MACs hmac-sha1 +<% end -%> +<% end -%> + +<% unless (s=scope.lookupvar('::sshd::tail_additional_options')).empty? -%> +<%= s %> +<% end -%> diff --git a/puppet/modules/sshd/templates/sshd_config/Gentoo.erb b/puppet/modules/sshd/templates/sshd_config/Gentoo.erb new file mode 100644 index 00000000..022a26e7 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/Gentoo.erb @@ -0,0 +1,164 @@ +#	$OpenBSD: sshd_config,v 1.75 2007/03/19 01:01:29 djm Exp $ + +# This is the sshd server system-wide configuration file.  See +# sshd_config(5) for more information. + +# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented.  Uncommented options change a +# default value. + +<% unless (s=scope.lookupvar('::sshd::head_additional_options')).empty? -%> +<%= s %> +<% end -%> + +<% scope.lookupvar('::sshd::ports').to_a.each do |port| -%> +<% if port == 'off' -%> +#Port -- disabled by puppet +<% else -%> +Port <%= port %> +<% end -%> +<% end -%> + +# Use these options to restrict which interfaces/protocols sshd will bind to +<% scope.lookupvar('::sshd::listen_address').to_a.each do |address| -%> +ListenAddress <%= address %> +<% end -%> +#AddressFamily any + +# Disable legacy (protocol version 1) support in the server for new +# installations. In future the default will change to require explicit +# activation of protocol 1 +Protocol 2 + +# HostKey for protocol version 1 +#HostKey /etc/ssh/ssh_host_key +# HostKeys for protocol version 2 +#HostKey /etc/ssh/ssh_host_rsa_key +#HostKey /etc/ssh/ssh_host_dsa_key + +# Lifetime and size of ephemeral version 1 server key +#KeyRegenerationInterval 1h +#ServerKeyBits 768 + +# Logging +# obsoletes QuietMode and FascistLogging +#SyslogFacility AUTH +#LogLevel INFO + +# Authentication: + +#LoginGraceTime 2m +PermitRootLogin <%= scope.lookupvar('::sshd::permit_root_login') %> + +StrictModes <%= scope.lookupvar('::sshd::strict_modes') %> + +#MaxAuthTries 6 + +RSAAuthentication <%= scope.lookupvar('::sshd::rsa_authentication') %> + +PubkeyAuthentication <%= scope.lookupvar('::sshd::pubkey_authentication') %> + +AuthorizedKeysFile <%= scope.lookupvar('::sshd::authorized_keys_file') %> + +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +RhostsRSAAuthentication <%= scope.lookupvar('::sshd::rhosts_rsa_authentication') %> + +# similar for protocol version 2 +HostbasedAuthentication <%= scope.lookupvar('::sshd::hostbased_authentication') %> + +# Change to yes if you don't trust ~/.ssh/known_hosts for +# RhostsRSAAuthentication and HostbasedAuthentication +#IgnoreUserKnownHosts no + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts <%= scope.lookupvar('::sshd::ignore_rhosts') %> + +# To disable tunneled clear text passwords, change to no here! +PasswordAuthentication <%= scope.lookupvar('::sshd::password_authentication') %> + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords <%= scope.lookupvar('::sshd::permit_empty_passwords') %> + +# Change to no to disable s/key passwords +ChallengeResponseAuthentication <%= scope.lookupvar('::sshd::challenge_response_authentication') %> + +# Kerberos options +#KerberosAuthentication no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes +#KerberosGetAFSToken no + +# GSSAPI options +#GSSAPIAuthentication no +#GSSAPICleanupCredentials yes +#GSSAPIStrictAcceptorCheck yes +#GSSAPIKeyExchange no + +# Set this to 'yes' to enable PAM authentication, account processing,  +# and session processing. If this is enabled, PAM authentication will  +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication.  Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM <%= scope.lookupvar('::sshd::use_pam') %> + +AllowTcpForwarding <%= scope.lookupvar('::sshd::tcp_forwarding') %> + +#GatewayPorts no +X11Forwarding <%= scope.lookupvar('::sshd::x11_forwarding') %> +#X11DisplayOffset 10 +#X11UseLocalhost yes +PrintMotd <%= scope.lookupvar('::sshd::print_motd') %> +#PrintLastLog yes +#TCPKeepAlive yes +#UseLogin no +#UsePrivilegeSeparation yes +#PermitUserEnvironment no +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#UseDNS yes +#PidFile /var/run/sshd.pid +#MaxStartups 10 +#PermitTunnel no + +# no default banner path +#Banner /some/path + +# override default of no subsystems +Subsystem      sftp    <%= (s=scope.lookupvar('::sshd::sftp_subsystem')).empty? ? '/usr/lib/misc/sftp-server' : s %> + +# Example of overriding settings on a per-user basis +#Match User anoncvs +#	X11Forwarding no +#	AllowTcpForwarding no +#	ForceCommand cvs server + +<% unless (s=scope.lookupvar('::sshd::allowed_users')).empty? -%> +AllowUsers <%= s %> +<% end -%> +<% unless (s=scope.lookupvar('::sshd::allowed_groups')).empty? -%> +AllowGroups <%= s %> +<%- end -%> + +<% if scope.lookupvar('::sshd::hardened') == 'yes' -%> +<% if (scope.function_versioncmp([scope.lookupvar('::ssh_version'),'6.5'])) >= 0 -%> +KexAlgorithms curve25519-sha256@libssh.org +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com +<% else -%> +Ciphers aes256-ctr +MACs hmac-sha1 +<% end -%> +<% end -%> + +<% unless (s=scope.lookupvar('::sshd::tail_additional_options')).empty? -%> +<%= s %> +<% end -%> + diff --git a/puppet/modules/sshd/templates/sshd_config/OpenBSD.erb b/puppet/modules/sshd/templates/sshd_config/OpenBSD.erb new file mode 100644 index 00000000..db730300 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/OpenBSD.erb @@ -0,0 +1,144 @@ +#	$OpenBSD: sshd_config,v 1.74 2006/07/19 13:07:10 dtucker Exp $ + +# This is the sshd server system-wide configuration file.  See +# sshd_config(5) for more information. + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented.  Uncommented options change a +# default value. + +<% unless (s=scope.lookupvar('::sshd::head_additional_options')).empty? -%> +<%= s %> +<% end -%> + +<% scope.lookupvar('::sshd::ports').to_a.each do |port| -%> +<% if port == 'off' -%> +#Port -- disabled by puppet +<% else -%> +Port <%= port %> +<% end -%> +<% end -%> + +# Use these options to restrict which interfaces/protocols sshd will bind to +<% scope.lookupvar('::sshd::listen_address').to_a.each do |address| -%> +ListenAddress <%= address %> +<% end -%> +#Protocol 2,1 +#AddressFamily any + +# HostKey for protocol version 1 +#HostKey /etc/ssh/ssh_host_key +# HostKeys for protocol version 2 +#HostKey /etc/ssh/ssh_host_rsa_key +#HostKey /etc/ssh/ssh_host_dsa_key + +# Lifetime and size of ephemeral version 1 server key +#KeyRegenerationInterval 1h +#ServerKeyBits 768 + +# Logging +# obsoletes QuietMode and FascistLogging +#SyslogFacility AUTH +#LogLevel INFO + +# Authentication: + +#LoginGraceTime 2m +PermitRootLogin <%= scope.lookupvar('::sshd::permit_root_login') %> + +StrictModes <%= scope.lookupvar('::sshd::strict_modes') %> + +#MaxAuthTries 6 + +RSAAuthentication <%= scope.lookupvar('::sshd::rsa_authentication') %> + +PubkeyAuthentication <%= scope.lookupvar('::sshd::pubkey_authentication') %> + +AuthorizedKeysFile <%= scope.lookupvar('::sshd::authorized_keys_file') %> + +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +RhostsRSAAuthentication <%= scope.lookupvar('::sshd::rhosts_rsa_authentication') %> + +# similar for protocol version 2 +HostbasedAuthentication <%= scope.lookupvar('::sshd::hostbased_authentication') %> + +# Change to yes if you don't trust ~/.ssh/known_hosts for +# RhostsRSAAuthentication and HostbasedAuthentication +#IgnoreUserKnownHosts no + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts <%= scope.lookupvar('::sshd::ignore_rhosts') %> + +# To disable tunneled clear text passwords, change to no here! +PasswordAuthentication <%= scope.lookupvar('::sshd::password_authentication') %> + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords <%= scope.lookupvar('::sshd::permit_empty_passwords') %> + +# Change to no to disable s/key passwords +ChallengeResponseAuthentication <%= scope.lookupvar('::sshd::challenge_response_authentication') %> + +# Kerberos options +#KerberosAuthentication no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes +#KerberosGetAFSToken no + +# GSSAPI options +#GSSAPIAuthentication no +#GSSAPICleanupCredentials yes + +AllowTcpForwarding <%= scope.lookupvar('::sshd::tcp_forwarding') %> + +#GatewayPorts no +X11Forwarding <%= scope.lookupvar('::sshd::x11_forwarding') %> +#X11DisplayOffset 10 +#X11UseLocalhost yes +PrintMotd <%= scope.lookupvar('::sshd::print_motd') %> +#PrintLastLog yes +#TCPKeepAlive yes +#UseLogin no +#UsePrivilegeSeparation yes +#PermitUserEnvironment no +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#UseDNS yes +#PidFile /var/run/sshd.pid +#MaxStartups 10 +#PermitTunnel no + +# no default banner path +#Banner /some/path + +# override default of no subsystems +Subsystem      sftp    <%= (s=scope.lookupvar('::sshd::sftp_subsystem')).empty? ? '/usr/libexec/sftp-server' : s %> + +<% unless (s=scope.lookupvar('::sshd::allowed_users')).empty? -%> +AllowUsers <%= s %> +<% end -%> +<% unless (s=scope.lookupvar('::sshd::allowed_groups')).empty? -%> +AllowGroups <%= s %> +<%- end -%> + +# Example of overriding settings on a per-user basis +#Match User anoncvs +#	X11Forwarding no +#	AllowTcpForwarding no +#	ForceCommand cvs server + +<% if scope.lookupvar('::sshd::hardened') == 'yes' -%> +<% if (scope.function_versioncmp([scope.lookupvar('::ssh_version'),'6.5'])) >= 0 -%> +KexAlgorithms curve25519-sha256@libssh.org +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com +<% else -%> +Ciphers aes256-ctr +MACs hmac-sha1 +<% end -%> +<% end -%> + +<% unless (s=scope.lookupvar('::sshd::tail_additional_options')).empty? -%> +<%= s %> +<% end -%> diff --git a/puppet/modules/sshd/templates/sshd_config/Ubuntu.erb b/puppet/modules/sshd/templates/sshd_config/Ubuntu.erb new file mode 100644 index 00000000..a326ab87 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/Ubuntu.erb @@ -0,0 +1,133 @@ +# This file is managed by Puppet, all local modifications will be overwritten +# +# Package generated configuration file +# See the sshd(8) manpage for details + +<% unless (s=scope.lookupvar('::sshd::head_additional_options')).empty? -%> +<%= s %> +<% end -%> + +# What ports, IPs and protocols we listen for +<% scope.lookupvar('::sshd::ports').to_a.each do |port| -%> +<% if port == 'off' -%> +#Port -- disabled by puppet +<% else -%> +Port <%= port %> +<% end -%> +<% end -%> + +# Use these options to restrict which interfaces/protocols sshd will bind to +<% scope.lookupvar('::sshd::listen_address').to_a.each do |address| -%> +ListenAddress <%= address %> +<% end -%> +Protocol 2 +# HostKeys for protocol version 2 +<% scope.lookupvar('::sshd::hostkey_type').to_a.each do |hostkey_type| -%> +HostKey /etc/ssh/ssh_host_<%=hostkey_type %>_key +<% end -%> + +#Privilege Separation is turned on for security +UsePrivilegeSeparation yes + +# Lifetime and size of ephemeral version 1 server key +KeyRegenerationInterval 3600 +ServerKeyBits 768 + +# Logging +SyslogFacility AUTH +LogLevel INFO + +# Authentication: +LoginGraceTime 120 +PermitRootLogin <%= scope.lookupvar('::sshd::permit_root_login') %> + +StrictModes <%= scope.lookupvar('::sshd::strict_modes') %> + +RSAAuthentication <%= scope.lookupvar('::sshd::rsa_authentication') %> + +PubkeyAuthentication <%= scope.lookupvar('::sshd::pubkey_authentication') %> + +AuthorizedKeysFile <%= scope.lookupvar('::sshd::authorized_keys_file') %> + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts <%= scope.lookupvar('::sshd::ignore_rhosts') %> +# For this to work you will also need host keys in /etc/ssh_known_hosts +RhostsRSAAuthentication <%= scope.lookupvar('::sshd::rhosts_rsa_authentication') %> +# similar for protocol version 2 +HostbasedAuthentication <%= scope.lookupvar('::sshd::hostbased_authentication') %> +# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication +#IgnoreUserKnownHosts yes + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords <%= scope.lookupvar('::sshd::permit_empty_passwords') %> + +# Change to yes to enable challenge-response passwords (beware issues with +# some PAM modules and threads) +ChallengeResponseAuthentication <%= scope.lookupvar('::sshd::challenge_response_authentication') %> + +# To disable tunneled clear text passwords, change to no here! +PasswordAuthentication <%= scope.lookupvar('::sshd::password_authentication') %> + +# Kerberos options +KerberosAuthentication <%= scope.lookupvar('::sshd::kerberos_authentication') %> +KerberosOrLocalPasswd <%= scope.lookupvar('::sshd::kerberos_orlocalpasswd') %> +KerberosTicketCleanup <%= scope.lookupvar('::sshd::kerberos_ticketcleanup') %> + +# GSSAPI options +GSSAPIAuthentication <%= scope.lookupvar('::sshd::gssapi_authentication') %> +GSSAPICleanupCredentials <%= scope.lookupvar('::sshd::gssapi_cleanupcredentials') %> + +X11Forwarding <%= scope.lookupvar('::sshd::x11_forwarding') %> +X11DisplayOffset 10 +PrintMotd <%= scope.lookupvar('::sshd::print_motd') %> +PrintLastLog yes +TCPKeepAlive yes + +#UseLogin no + +#MaxStartups 10:30:60 +#Banner /etc/issue.net +# do not reveal debian version (default is yes) +DebianBanner no + +# Allow client to pass locale environment variables +AcceptEnv LANG LC_* + +Subsystem      sftp    <%= (s=scope.lookupvar('::sshd::sftp_subsystem')).empty? ? '/usr/lib/openssh/sftp-server' : s %> + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication.  Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM <%= scope.lookupvar('::sshd::use_pam') %> + +AllowTcpForwarding <%= scope.lookupvar('::sshd::tcp_forwarding') %> + +AllowAgentForwarding <%= scope.lookupvar('::sshd::agent_forwarding') %> + +<% unless (s=scope.lookupvar('::sshd::allowed_users')).empty? -%> +AllowUsers <%= s %> +<% end -%> +<% unless (s=scope.lookupvar('::sshd::allowed_groups')).empty? -%> +AllowGroups <%= s %> +<%- end -%> + +<% if scope.lookupvar('::sshd::hardened') == 'yes' -%> +<% if (scope.function_versioncmp([scope.lookupvar('::ssh_version'),'6.5'])) >= 0 -%> +KexAlgorithms curve25519-sha256@libssh.org +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com +<% else -%> +Ciphers aes256-ctr +MACs hmac-sha1 +<% end -%> +<% end -%> + +<% unless (s=scope.lookupvar('::sshd::tail_additional_options')).empty? -%> +<%= s %> +<% end -%> diff --git a/puppet/modules/sshd/templates/sshd_config/Ubuntu_lucid.erb b/puppet/modules/sshd/templates/sshd_config/Ubuntu_lucid.erb new file mode 100644 index 00000000..be7c56d0 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/Ubuntu_lucid.erb @@ -0,0 +1,136 @@ +# Package generated configuration file +# See the sshd(8) manpage for details + +<% unless (s=scope.lookupvar('::sshd::head_additional_options')).empty? -%> +<%= s %> +<% end -%> + +# What ports, IPs and protocols we listen for +<% scope.lookupvar('::sshd::ports').to_a.each do |port| -%> +<% if port == 'off' -%> +#Port -- disabled by puppet +<% else -%> +Port <%= port %> +<% end -%> +<% end -%> + +# Use these options to restrict which interfaces/protocols sshd will bind to +<% scope.lookupvar('::sshd::listen_address').to_a.each do |address| -%> +ListenAddress <%= address %> +<% end -%> +Protocol 2 +# HostKeys for protocol version 2 +<% scope.lookupvar('::sshd::hostkey_type').to_a.each do |hostkey_type| -%> +HostKey /etc/ssh/ssh_host_<%=hostkey_type %>_key +<% end -%> + +#Privilege Separation is turned on for security +UsePrivilegeSeparation yes + +# ...but breaks Pam auth via kbdint, so we have to turn it off +# Use PAM authentication via keyboard-interactive so PAM modules can +# properly interface with the user (off due to PrivSep) +#PAMAuthenticationViaKbdInt no +# Lifetime and size of ephemeral version 1 server key +KeyRegenerationInterval 3600 +ServerKeyBits 768 + +# Logging +SyslogFacility AUTH +LogLevel INFO + +# Authentication: +LoginGraceTime 600 +PermitRootLogin <%= scope.lookupvar('::sshd::permit_root_login') %> + +StrictModes <%= scope.lookupvar('::sshd::strict_modes') %> + +RSAAuthentication <%= scope.lookupvar('::sshd::rsa_authentication') %> + +PubkeyAuthentication <%= scope.lookupvar('::sshd::pubkey_authentication') %> + +AuthorizedKeysFile <%= scope.lookupvar('::sshd::authorized_keys_file') %> + +# For this to work you will also need host keys in /etc/ssh_known_hosts +RhostsRSAAuthentication <%= scope.lookupvar('::sshd::rhosts_rsa_authentication') %> + +# Don't read the user's ~/.rhosts and ~/.shosts files +IgnoreRhosts <%= scope.lookupvar('::sshd::ignore_rhosts') %> + +# similar for protocol version 2 +HostbasedAuthentication <%= scope.lookupvar('::sshd::hostbased_authentication') %> + +# Uncomment if you don't trust ~/.ssh/known_hosts for RhostsRSAAuthentication +#IgnoreUserKnownHosts yes + +# To enable empty passwords, change to yes (NOT RECOMMENDED) +PermitEmptyPasswords <%= scope.lookupvar('::sshd::permit_empty_passwords') %> + +# Change to no to disable s/key passwords +ChallengeResponseAuthentication <%= scope.lookupvar('::sshd::challenge_response_authentication') %> + +# To disable tunneled clear text passwords, change to no here! +PasswordAuthentication <%= scope.lookupvar('::sshd::password_authentication') %> + +# To change Kerberos options +#KerberosAuthentication no +#KerberosOrLocalPasswd yes +#AFSTokenPassing no +#KerberosTicketCleanup no + +# Kerberos TGT Passing does only work with the AFS kaserver +#KerberosTgtPassing yes + +X11Forwarding <%= scope.lookupvar('::sshd::x11_forwarding') %> +X11DisplayOffset 10 +KeepAlive yes +#UseLogin no + +#MaxStartups 10:30:60 +#Banner /etc/issue.net +# do not reveal debian version (default is yes) +DebianBanner no +#ReverseMappingCheck yes + +Subsystem      sftp    <%= (s=scope.lookupvar('::sshd::sftp_subsystem')).empty? ? '/usr/lib/openssh/sftp-server' : s %> + +# Set this to 'yes' to enable PAM authentication, account processing,  +# and session processing. If this is enabled, PAM authentication will  +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication.  Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +UsePAM <%= scope.lookupvar('::sshd::use_pam') %> + +HostbasedUsesNameFromPacketOnly yes + +AllowTcpForwarding <%= scope.lookupvar('::sshd::tcp_forwarding') %> + +AllowAgentForwarding <%= scope.lookupvar('::sshd::agent_forwarding') %> + +<% unless (s=scope.lookupvar('::sshd::allowed_users')).empty? -%> +AllowUsers <%= s %> +<% end -%> +<% unless (s=scope.lookupvar('::sshd::allowed_groups')).empty? -%> +AllowGroups <%= s %> +<%- end -%> + +PrintMotd <%= scope.lookupvar('::sshd::print_motd') %> + +<% if scope.lookupvar('::sshd::hardened') == 'yes' -%> +<% if (scope.function_versioncmp([scope.lookupvar('::ssh_version'),'6.5'])) >= 0 -%> +KexAlgorithms curve25519-sha256@libssh.org +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctr +MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com +<% else -%> +Ciphers aes256-ctr +MACs hmac-sha1 +<% end -%> +<% end -%> + +<% unless (s=scope.lookupvar('::sshd::tail_additional_options')).empty? -%> +<%= s %> +<% end -%> diff --git a/puppet/modules/sshd/templates/sshd_config/Ubuntu_oneiric.erb b/puppet/modules/sshd/templates/sshd_config/Ubuntu_oneiric.erb new file mode 120000 index 00000000..ccfb67c8 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/Ubuntu_oneiric.erb @@ -0,0 +1 @@ +Ubuntu_lucid.erb
\ No newline at end of file diff --git a/puppet/modules/sshd/templates/sshd_config/Ubuntu_precise.erb b/puppet/modules/sshd/templates/sshd_config/Ubuntu_precise.erb new file mode 120000 index 00000000..6502bfce --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/Ubuntu_precise.erb @@ -0,0 +1 @@ +Ubuntu.erb
\ No newline at end of file diff --git a/puppet/modules/sshd/templates/sshd_config/XenServer_xenenterprise.erb b/puppet/modules/sshd/templates/sshd_config/XenServer_xenenterprise.erb new file mode 120000 index 00000000..71b767a5 --- /dev/null +++ b/puppet/modules/sshd/templates/sshd_config/XenServer_xenenterprise.erb @@ -0,0 +1 @@ +CentOS_6.erb
\ No newline at end of file diff --git a/puppet/modules/templatewlv/Modulefile b/puppet/modules/templatewlv/Modulefile new file mode 100644 index 00000000..8007a070 --- /dev/null +++ b/puppet/modules/templatewlv/Modulefile @@ -0,0 +1,11 @@ +name    'duritong-templatewlv' +version '0.0.1' +source 'https://github.com/duritong/puppet-templatewlv.git' +author 'duritong' +license 'Apache License, Version 2.0' +summary 'Template With Local Variables' +description 'Pass local variables to templates' +project_page 'https://github.com/duritong/puppet-templatewlv' + +## Add dependencies, if any: +# dependency 'username/name', '>= 1.2.0' diff --git a/puppet/modules/templatewlv/README.md b/puppet/modules/templatewlv/README.md new file mode 100644 index 00000000..5ab01e45 --- /dev/null +++ b/puppet/modules/templatewlv/README.md @@ -0,0 +1,21 @@ +# templatewlv + +## Template With Local Variables + +A wrapper around puppet's template function. See +[the templating docs](http://docs.puppetlabs.com/guides/templating.html) for  +the basic functionality. + +Additionally, you can pass a hash, as the last argument, which will be turned into +local variables and available to the template itself. This will allow you  to define +variables in a template and pass them down to a template you include in the current +template. An example: + +    scope.function_templatewlv(['sub_template', { 'local_var' => 'value' }]) +   +Note that if multiple templates are specified, their output is all +concatenated and returned as the output of the function. + +# Who - License + +duritong - Apache License, Version 2.0 diff --git a/puppet/modules/templatewlv/lib/puppet/parser/functions/templatewlv.rb b/puppet/modules/templatewlv/lib/puppet/parser/functions/templatewlv.rb new file mode 100644 index 00000000..c9579e2c --- /dev/null +++ b/puppet/modules/templatewlv/lib/puppet/parser/functions/templatewlv.rb @@ -0,0 +1,41 @@ +require File.join(File.dirname(__FILE__),'../templatewrapperwlv') +Puppet::Parser::Functions::newfunction(:templatewlv, :type => :rvalue, :arity => -2, :doc => +  "A wrapper around puppet's template function. See +  [the templating docs](http://docs.puppetlabs.com/guides/templating.html) for  +  the basic functionality. + +  Additionally, you can pass a hash, as the last argument, which will be turned into +  local variables and available to the template itself. This will allow you  to define +  variables in a template and pass them down to a template you include in the current +  template. An example: + +    scope.function_templatewlv(['sub_template', { 'local_var' => 'value' }]) +   +  Note that if multiple templates are specified, their output is all +  concatenated and returned as the output of the function.") do |vals| + +    if vals.last.is_a?(Hash) +      local_vars = vals.last +      local_vals = vals[0..-2] +    else +      local_vars = {} +      local_vals = vals +    end + +    result = nil +    local_vals.collect do |file| +      # Use a wrapper, so the template can't get access to the full +      # Scope object. +      debug "Retrieving template #{file}" + +      wrapper = Puppet::Parser::TemplateWrapperWlv.new(self,local_vars) +      wrapper.file = file +      begin +        wrapper.result +      rescue => detail +        info = detail.backtrace.first.split(':') +        raise Puppet::ParseError, +          "Failed to parse template #{file}:\n  Filepath: #{info[0]}\n  Line: #{info[1]}\n  Detail: #{detail}\n" +      end +    end.join("") +end diff --git a/puppet/modules/templatewlv/lib/puppet/parser/templatewrapperwlv.rb b/puppet/modules/templatewlv/lib/puppet/parser/templatewrapperwlv.rb new file mode 100644 index 00000000..f1753e18 --- /dev/null +++ b/puppet/modules/templatewlv/lib/puppet/parser/templatewrapperwlv.rb @@ -0,0 +1,39 @@ +# A wrapper for templates, that allows you to additionally define +# local variables +class Puppet::Parser::TemplateWrapperWlv < Puppet::Parser::TemplateWrapper +  attr_reader :local_vars +  def initialize(scope, local_vars) +    super(scope) +    @local_vars = local_vars +  end + +  # Should return true if a variable is defined, false if it is not +  def has_variable?(name) +    super(name) || local_vars.keys.include?(name.to_s) +  end + +  def method_missing(name, *args) +    if local_vars.keys.include?(n=name.to_s) +      local_vars[n] +    else +      super(name, *args) +    end +  end + +  def result(string = nil) +    # Expose all the variables in our scope as instance variables of the +    # current object, making it possible to access them without conflict +    # to the regular methods. +    benchmark(:debug, "Bound local template variables for #{@__file__}") do +      local_vars.each do |name, value| +        if name.kind_of?(String) +          realname = name.gsub(/[^\w]/, "_") +        else +          realname = name +        end +        instance_variable_set("@#{realname}", value) +      end +    end +    super(string) +  end +end diff --git a/puppet/modules/try/README.md b/puppet/modules/try/README.md new file mode 100644 index 00000000..3888661e --- /dev/null +++ b/puppet/modules/try/README.md @@ -0,0 +1,13 @@ +This module provides a "try" wrapper around common resource types. + +For example: + +    try::file { +      '/path/to/file': +        ensure => 'link', +        target => $target; +    } + +This will work just like `file`, but will silently fail if `$target` is undefined or the file does not exist. + +So far, only `file` type with symlinks works. diff --git a/puppet/modules/try/manifests/file.pp b/puppet/modules/try/manifests/file.pp new file mode 100644 index 00000000..2493d343 --- /dev/null +++ b/puppet/modules/try/manifests/file.pp @@ -0,0 +1,114 @@ +# +# Works like the built-in type "file", but gets gracefully ignored if the target/source does not exist or is undefined. +# +# Also, if the source or target doesn't exist, and the destination is a git repo, then the file is restored from git. +# +# All executable paths are hardcoded to their paths in debian. +# +# known limitations: +# * this is far too noisy +# * $restore does not work for directories +# * only file:// $source is supported +# * $content is not supported, only $target or $source. +# * does not auto-require all the parent directories like 'file' does +# +define try::file ( +  $ensure = undef, +  $target = undef, +  $source = undef, +  $owner = undef, +  $group = undef, +  $recurse = undef, +  $purge = undef, +  $force = undef, +  $mode = undef, +  $restore = true) { + +  # dummy exec to propagate requires: +  # metaparameter 'require' will get triggered by this dummy exec +  # so then we just need to depend on this to capture all requires. +  # exec { $name: command => "/bin/true" } + +  exec { +    "chmod_${name}": +      command => "/bin/chmod -R ${mode} '${name}'", +      onlyif => "/usr/bin/test ${mode}", +      refreshonly => true, +      loglevel => debug; +    "chown_${name}": +      command => "/bin/chown -R ${owner} '${name}'", +      onlyif => "/usr/bin/test ${owner}", +      refreshonly => true, +      loglevel => debug; +    "chgrp_${name}": +      command => "/bin/chgrp -R ${group} '${name}'", +      onlyif => "/usr/bin/test ${group}", +      refreshonly => true, +      loglevel => debug; +  } + +  if $target { +    exec { "symlink_${name}": +      command => "/bin/ln -s ${target} ${name}", +      onlyif  => "/usr/bin/test -d '${target}'", +    } +  } elsif $source { +    if $ensure == 'directory' { +      if $purge { +        exec { "rsync_${name}": +          command => "/usr/bin/rsync -r --delete '${source}/' '${name}'", +          onlyif  => "/usr/bin/test -d '${source}'", +          unless  => "/usr/bin/diff -rq '${source}' '${name}'", +          notify  => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]] +        } +      } else { +        exec { "cp_r_${name}": +          command => "/bin/cp -r '${source}' '${name}'", +          onlyif  => "/usr/bin/test -d '${source}'", +          unless  => "/usr/bin/diff -rq '${source}' '${name}'", +          notify  => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]] +        } +      } +    } else { +      exec { "cp_${name}": +        command => "/bin/cp --remove-destination '${source}' '${name}'", +        onlyif  => "/usr/bin/test -e '${source}'", +        unless  => "/usr/bin/test ! -h '${name}' && /usr/bin/diff -q '${source}' '${name}'", +        notify  => [Exec["chmod_${name}"], Exec["chown_${name}"], Exec["chgrp_${name}"]] +      } +    } +  } + +  # +  # if the target/source does not exist (or is undef), and the file happens to be in a git repo, +  # then restore the file to its original state. +  # + +  if $target { +    $target_or_source = $target +  } else { +    $target_or_source = $source +  } + +  if ($target_or_source == undef) or $restore { +    $file_basename = basename($name) +    $file_dirname  = dirname($name) +    $command = "git rev-parse && unlink '${name}'; git checkout -- '${file_basename}' && chown --reference='${file_dirname}' '${name}'; true" +    debug($command) + +    if $target_or_source == undef { +      exec { "restore_${name}": +        command => $command, +        cwd => $file_dirname, +        loglevel => info; +      } +    } else { +      exec { "restore_${name}": +        unless => "/usr/bin/test -e '${target_or_source}'", +        command => $command, +        cwd => $file_dirname, +        loglevel => info; +      } +    } +  } +} diff --git a/puppet/modules/try/manifests/init.pp b/puppet/modules/try/manifests/init.pp new file mode 100644 index 00000000..1d2108c9 --- /dev/null +++ b/puppet/modules/try/manifests/init.pp @@ -0,0 +1,3 @@ +class try { + +} diff --git a/puppet/modules/x509/manifests/base.pp b/puppet/modules/x509/manifests/base.pp new file mode 100644 index 00000000..b88cce64 --- /dev/null +++ b/puppet/modules/x509/manifests/base.pp @@ -0,0 +1,45 @@ +class x509::base { +  include x509::variables + +  package { [ 'ssl-cert', 'ca-certificates' ]: +    ensure => installed; +  } + +  group { 'ssl-cert': +    ensure  => present, +    system  => true, +    require => Package['ssl-cert']; +  } + +  file { +    $x509::variables::root: +      ensure  => directory, +      mode    => '0755', +      owner   => root, +      group   => root; + +    $x509::variables::keys: +      ensure  => directory, +      mode    => '0750', +      owner   => root, +      group   => ssl-cert; + +    $x509::variables::certs: +      ensure  => directory, +      mode    => '0755', +      owner   => root, +      group   => root; + +    $x509::variables::local_CAs: +      ensure  => directory, +      mode    => '2775', +      owner   => root, +      group   => root; +  } + +  exec { 'update-ca-certificates': +    command     => '/usr/sbin/update-ca-certificates', +    refreshonly => true, +    subscribe   => File[$x509::variables::local_CAs] +  } +} diff --git a/puppet/modules/x509/manifests/ca.pp b/puppet/modules/x509/manifests/ca.pp new file mode 100644 index 00000000..0e068cd3 --- /dev/null +++ b/puppet/modules/x509/manifests/ca.pp @@ -0,0 +1,34 @@ +define x509::ca ( +  $content = 'absent', +  $source  = 'absent' +) { +  include x509::variables +  include x509::base + +  file { "${x509::variables::local_CAs}/${name}.crt" : +    ensure  => file, +    mode    => '0444', +    group   => 'ssl-cert', +    require => Package['ca-certificates'], +    notify  => Exec['update-ca-certificates'], +  } +  case $content { +    'absent': { +      $real_source = $source ? { +        'absent' => [ +                     "puppet:///modules/site_x509/CAs/${::fqdn}/${name}.crt", +                     "puppet:///modules/site_x509/CAs/${name}.crt" +                     ], +        default => "puppet:///$source", +      } +      File["${x509::variables::local_CAs}/${name}.crt"] { +        source => $real_source +      } +    } +    default: { +      File["${x509::variables::local_CAs}/${name}.crt"] { +        content => $content +      } +    } +  } +} diff --git a/puppet/modules/x509/manifests/cert.pp b/puppet/modules/x509/manifests/cert.pp new file mode 100644 index 00000000..0aafb76d --- /dev/null +++ b/puppet/modules/x509/manifests/cert.pp @@ -0,0 +1,34 @@ +define x509::cert ( +  $content = 'absent', +  $source  = 'absent' +) { +  include x509::variables +  include x509::base + +  file { "${x509::variables::certs}/${name}.crt": +    ensure  => file, +    mode    => '0444', +    group   => 'ssl-cert', +    require => Package['ssl-cert'] +  } + +  case $content { +    'absent': { +      $real_source = $source ? { +        'absent' => [ +                     "puppet:///modules/site_x509/certs/${::fqdn}/${name}.crt", +                     "puppet:///modules/site_x509/certs/${name}.crt" +                     ], +        default => "puppet:///$source", +      } +      File["${x509::variables::certs}/${name}.crt"] { +        source => $real_source +      } +    } +    default: { +      File["${x509::variables::certs}/${name}.crt"] { +        content => $content +      } +    } +  } +} diff --git a/puppet/modules/x509/manifests/init.pp b/puppet/modules/x509/manifests/init.pp new file mode 100644 index 00000000..8283e482 --- /dev/null +++ b/puppet/modules/x509/manifests/init.pp @@ -0,0 +1,2 @@ +class x509 { +} diff --git a/puppet/modules/x509/manifests/key.pp b/puppet/modules/x509/manifests/key.pp new file mode 100644 index 00000000..fd7e25fd --- /dev/null +++ b/puppet/modules/x509/manifests/key.pp @@ -0,0 +1,37 @@ +define x509::key ( +  $content = 'absent', +  $source  = 'absent', +  $owner   = 'root', +  $group   = 'ssl-cert' +) { +  include x509::variables +  include x509::base + +  file { "${x509::variables::keys}/${name}.key": +    ensure  => file, +    mode    => '0640', +    owner   => $owner, +    group   => $group, +    require => Package['ssl-cert'] +  } + +  case $content { +    'absent': { +      $real_source = $source ? { +        'absent' => [ +                     "puppet:///modules/site_x509/keys/${::fqdn}/${name}.key", +                     "puppet:///modules/site_x509/keys/${name}.key" +                     ], +        default => "puppet:///$source", +      } +      File["${x509::variables::keys}/${name}.key"] { +        source => $real_source +      } +    } +    default: { +      File["${x509::variables::keys}/${name}.key"] { +        content => $content +      } +    } +  } +} diff --git a/puppet/modules/x509/manifests/variables.pp b/puppet/modules/x509/manifests/variables.pp new file mode 100644 index 00000000..e6bd2359 --- /dev/null +++ b/puppet/modules/x509/manifests/variables.pp @@ -0,0 +1,7 @@ +class x509::variables { +  $root           = '/etc/x509' +  $certs          = "${root}/certs" +  $keys           = "${root}/keys" +  $x509_chain     = "${root}/certs" +  $local_CAs      = '/usr/local/share/ca-certificates' +}  | 
