diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 597564c90ea..e7c87565b0f 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -206,6 +206,7 @@ steps: command: ".buildkite/scripts/steps/k8s-extended-tests.sh" artifact_paths: - "build/k8s-logs*/*" + - "build/k8s-logs*/**/*" - "build/TEST-**" - "build/diagnostics/*" agents: diff --git a/NOTICE.txt b/NOTICE.txt index dcdfd816ac2..c277e84f2a7 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -389,6 +389,207 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- +Dependency : github.com/docker/docker +Version: v26.1.4+incompatible +Licence type (autodetected): Apache-2.0 +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/github.com/docker/docker@v26.1.4+incompatible/LICENSE: + + + Apache License + Version 2.0, January 2004 + https://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 + + Copyright 2013-2018 Docker, Inc. + + 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 + + https://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. + + -------------------------------------------------------------------------------- Dependency : github.com/docker/go-units Version: v0.5.0 @@ -14700,6 +14901,43 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +-------------------------------------------------------------------------------- +Dependency : golang.org/x/exp +Version: v0.0.0-20240506185415-9bf2ced13842 +Licence type (autodetected): BSD-3-Clause +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/LICENSE: + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + -------------------------------------------------------------------------------- Dependency : golang.org/x/sync Version: v0.7.0 @@ -16740,6 +16978,414 @@ Contents of probable licence file $GOMODCACHE/k8s.io/utils@v0.0.0-20230726121419 limitations under the License. +-------------------------------------------------------------------------------- +Dependency : kernel.org/pub/linux/libs/security/libcap/cap +Version: v1.2.70 +Licence type (autodetected): BSD-3-Clause +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/kernel.org/pub/linux/libs/security/libcap/cap@v1.2.70/License: + +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only */ + +Unless otherwise *explicitly* stated, the following text describes the +licensed conditions under which the contents of this libcap/cap release +may be used and distributed. + +The licensed conditions are one or the other of these two Licenses: + + - BSD 3-clause + - GPL v2.0 + +------------------------------------------------------------------------- +BSD 3-clause: +------------- + +Redistribution and use in source and binary forms of libcap/cap, with +or without modification, are permitted provided that the following +conditions are met: + +1. Redistributions of source code must retain any existing copyright + notice, and this entire permission notice in its entirety, + including the disclaimer of warranties. + +2. Redistributions in binary form must reproduce all prior and current + copyright notices, this list of conditions, and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +3. The name of any author may not be used to endorse or promote + products derived from this software without their specific prior + written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +------------------------------------------------------------------------- +GPL v2.0: +--------- + +ALTERNATIVELY, this product may be distributed under the terms of the +GNU General Public License (v2.0 - see below), in which case the +provisions of the GNU GPL are required INSTEAD OF the above +restrictions. (This clause is necessary due to a potential conflict +between the GNU GPL and the restrictions contained in a BSD-style +copyright.) + +------------------------- +Full text of gpl-2.0.txt: +------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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. + + -------------------------------------------------------------------------------- Dependency : sigs.k8s.io/e2e-framework Version: v0.4.0 @@ -19276,207 +19922,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------------- -Dependency : github.com/docker/docker -Version: v26.1.4+incompatible -Licence type (autodetected): Apache-2.0 --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/github.com/docker/docker@v26.1.4+incompatible/LICENSE: - - - Apache License - Version 2.0, January 2004 - https://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 - - Copyright 2013-2018 Docker, Inc. - - 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 - - https://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. - - -------------------------------------------------------------------------------- Dependency : github.com/docker/go-connections Version: v0.5.0 @@ -51959,43 +52404,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------------------------------- -Dependency : golang.org/x/exp -Version: v0.0.0-20240506185415-9bf2ced13842 -Licence type (autodetected): BSD-3-Clause --------------------------------------------------------------------------------- - -Contents of probable licence file $GOMODCACHE/golang.org/x/exp@v0.0.0-20240506185415-9bf2ced13842/LICENSE: - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -------------------------------------------------------------------------------- Dependency : golang.org/x/mod Version: v0.18.0 @@ -54047,6 +54455,414 @@ Contents of probable licence file $GOMODCACHE/k8s.io/kubelet@v0.29.3/LICENSE: limitations under the License. +-------------------------------------------------------------------------------- +Dependency : kernel.org/pub/linux/libs/security/libcap/psx +Version: v1.2.70 +Licence type (autodetected): BSD-3-Clause +-------------------------------------------------------------------------------- + +Contents of probable licence file $GOMODCACHE/kernel.org/pub/linux/libs/security/libcap/psx@v1.2.70/License: + +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only */ + +Unless otherwise *explicitly* stated, the following text describes the +licensed conditions under which the contents of this libcap/psx release +may be used and distributed. + +The licensed conditions are one or the other of these two Licenses: + + - BSD 3-clause + - GPL v2.0 + +------------------------------------------------------------------------- +BSD 3-clause: +------------- + +Redistribution and use in source and binary forms of libcap/psx, with +or without modification, are permitted provided that the following +conditions are met: + +1. Redistributions of source code must retain any existing copyright + notice, and this entire permission notice in its entirety, + including the disclaimer of warranties. + +2. Redistributions in binary form must reproduce all prior and current + copyright notices, this list of conditions, and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +3. The name of any author may not be used to endorse or promote + products derived from this software without their specific prior + written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +------------------------------------------------------------------------- +GPL v2.0: +--------- + +ALTERNATIVELY, this product may be distributed under the terms of the +GNU General Public License (v2.0 - see below), in which case the +provisions of the GNU GPL are required INSTEAD OF the above +restrictions. (This clause is necessary due to a potential conflict +between the GNU GPL and the restrictions contained in a BSD-style +copyright.) + +------------------------- +Full text of gpl-2.0.txt: +------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 2 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, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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. + + -------------------------------------------------------------------------------- Dependency : sigs.k8s.io/controller-runtime Version: v0.18.2 diff --git a/changelog/fragments/1718273218-container-init-capabilities.yaml b/changelog/fragments/1718273218-container-init-capabilities.yaml new file mode 100644 index 00000000000..2c9e59e3822 --- /dev/null +++ b/changelog/fragments/1718273218-container-init-capabilities.yaml @@ -0,0 +1,32 @@ +# Kind can be one of: +# - breaking-change: a change to previously-documented behavior +# - deprecation: functionality that is being removed in a later release +# - bug-fix: fixes a problem in a previous version +# - enhancement: extends functionality but does not break or fix existing behavior +# - feature: new functionality +# - known-issue: problems that we are aware of in a given version +# - security: impacts on the security of a product or a user’s deployment. +# - upgrade: important information for someone upgrading from a prior version +# - other: does not fit into any of the other categories +kind: feature + +# Change summary; a 80ish characters long description of the change. +summary: extend agent container initialisation to chown paths and raise capabilities for non-root + +# Long description; in case the summary is not enough to describe the change +# this field accommodate a description without length limits. +# NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment. +#description: + +# Affected component; usually one of "elastic-agent", "fleet-server", "filebeat", "metricbeat", "auditbeat", "all", etc. +component: elastic-agent + +# PR URL; optional; the PR number that added the changeset. +# If not present is automatically filled by the tooling finding the PR where this changelog fragment has been added. +# NOTE: the tooling supports backports, so it's able to fill the original PR number instead of the backport PR number. +# Please provide it if you are adding a fragment for a different PR. +pr: https://github.com/elastic/elastic-agent/pull/4925 + +# Issue URL; optional; the GitHub issue related to this changeset (either closes or is part of). +# If not present is automatically filled by the tooling with the issue linked to the PR number. +#issue: https://github.com/owner/repo/1234 diff --git a/deploy/kubernetes/elastic-agent-kustomize/default/elastic-agent-standalone/base/elastic-agent-standalone-daemonset.yaml b/deploy/kubernetes/elastic-agent-kustomize/default/elastic-agent-standalone/base/elastic-agent-standalone-daemonset.yaml index 0c5cddac5e5..14af7733688 100644 --- a/deploy/kubernetes/elastic-agent-kustomize/default/elastic-agent-standalone/base/elastic-agent-standalone-daemonset.yaml +++ b/deploy/kubernetes/elastic-agent-kustomize/default/elastic-agent-standalone/base/elastic-agent-standalone-daemonset.yaml @@ -66,7 +66,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name - # The following ELASTIC_NETINFO:false variable will disable the netinfo.enabled option of add-host-metadata processor. This will remove fields host.ip and host.mac. + # The following ELASTIC_NETINFO:false variable will disable the netinfo.enabled option of add-host-metadata processor. This will remove fields host.ip and host.mac. # For more info: https://www.elastic.co/guide/en/beats/metricbeat/current/add-host-metadata.html - name: ELASTIC_NETINFO value: "false" @@ -127,7 +127,7 @@ spec: volumes: - name: datastreams configMap: - defaultMode: 0640 + defaultMode: 0644 name: agent-node-datastreams - name: proc hostPath: diff --git a/deploy/kubernetes/elastic-agent-kustomize/ksm-autosharding/elastic-agent-standalone/base/elastic-agent-standalone-daemonset.yaml b/deploy/kubernetes/elastic-agent-kustomize/ksm-autosharding/elastic-agent-standalone/base/elastic-agent-standalone-daemonset.yaml index b9409ac6441..c73d58af508 100644 --- a/deploy/kubernetes/elastic-agent-kustomize/ksm-autosharding/elastic-agent-standalone/base/elastic-agent-standalone-daemonset.yaml +++ b/deploy/kubernetes/elastic-agent-kustomize/ksm-autosharding/elastic-agent-standalone/base/elastic-agent-standalone-daemonset.yaml @@ -66,7 +66,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name - # The following ELASTIC_NETINFO:false variable will disable the netinfo.enabled option of add-host-metadata processor. This will remove fields host.ip and host.mac. + # The following ELASTIC_NETINFO:false variable will disable the netinfo.enabled option of add-host-metadata processor. This will remove fields host.ip and host.mac. # For more info: https://www.elastic.co/guide/en/beats/metricbeat/current/add-host-metadata.html - name: ELASTIC_NETINFO value: "false" @@ -127,7 +127,7 @@ spec: volumes: - name: datastreams configMap: - defaultMode: 0640 + defaultMode: 0644 name: agent-node-datastreams - name: proc hostPath: diff --git a/deploy/kubernetes/elastic-agent-kustomize/ksm-autosharding/elastic-agent-standalone/extra/elastic-agent-standalone-statefulset.yaml b/deploy/kubernetes/elastic-agent-kustomize/ksm-autosharding/elastic-agent-standalone/extra/elastic-agent-standalone-statefulset.yaml index 4cc140ceb82..c3bc80e5897 100644 --- a/deploy/kubernetes/elastic-agent-kustomize/ksm-autosharding/elastic-agent-standalone/extra/elastic-agent-standalone-statefulset.yaml +++ b/deploy/kubernetes/elastic-agent-kustomize/ksm-autosharding/elastic-agent-standalone/extra/elastic-agent-standalone-statefulset.yaml @@ -66,7 +66,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name - # The following ELASTIC_NETINFO:false variable will disable the netinfo.enabled option of add-host-metadata processor. This will remove fields host.ip and host.mac. + # The following ELASTIC_NETINFO:false variable will disable the netinfo.enabled option of add-host-metadata processor. This will remove fields host.ip and host.mac. # For more info: https://www.elastic.co/guide/en/beats/metricbeat/current/add-host-metadata.html - name: ELASTIC_NETINFO value: "false" @@ -127,7 +127,7 @@ spec: volumes: - name: datastreams configMap: - defaultMode: 0640 + defaultMode: 0644 name: agent-ksm-datastreams - name: proc hostPath: diff --git a/deploy/kubernetes/elastic-agent-standalone-kubernetes.yaml b/deploy/kubernetes/elastic-agent-standalone-kubernetes.yaml index 0a566f06e0a..2cfdfbfd631 100644 --- a/deploy/kubernetes/elastic-agent-standalone-kubernetes.yaml +++ b/deploy/kubernetes/elastic-agent-standalone-kubernetes.yaml @@ -735,7 +735,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name - # The following ELASTIC_NETINFO:false variable will disable the netinfo.enabled option of add-host-metadata processor. This will remove fields host.ip and host.mac. + # The following ELASTIC_NETINFO:false variable will disable the netinfo.enabled option of add-host-metadata processor. This will remove fields host.ip and host.mac. # For more info: https://www.elastic.co/guide/en/beats/metricbeat/current/add-host-metadata.html - name: ELASTIC_NETINFO value: "false" @@ -796,7 +796,7 @@ spec: volumes: - name: datastreams configMap: - defaultMode: 0640 + defaultMode: 0644 name: agent-node-datastreams - name: proc hostPath: diff --git a/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-daemonset.yaml b/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-daemonset.yaml index 7f46b4f79e1..2cec1b96d9e 100644 --- a/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-daemonset.yaml +++ b/deploy/kubernetes/elastic-agent-standalone/elastic-agent-standalone-daemonset.yaml @@ -66,7 +66,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.name - # The following ELASTIC_NETINFO:false variable will disable the netinfo.enabled option of add-host-metadata processor. This will remove fields host.ip and host.mac. + # The following ELASTIC_NETINFO:false variable will disable the netinfo.enabled option of add-host-metadata processor. This will remove fields host.ip and host.mac. # For more info: https://www.elastic.co/guide/en/beats/metricbeat/current/add-host-metadata.html - name: ELASTIC_NETINFO value: "false" @@ -127,7 +127,7 @@ spec: volumes: - name: datastreams configMap: - defaultMode: 0640 + defaultMode: 0644 name: agent-node-datastreams - name: proc hostPath: diff --git a/dev-tools/mage/gotest.go b/dev-tools/mage/gotest.go index 3a99f2edd3d..837c2407bdf 100644 --- a/dev-tools/mage/gotest.go +++ b/dev-tools/mage/gotest.go @@ -176,6 +176,33 @@ func InstallGoTestTools() error { ) } +func GoTestBuild(ctx context.Context, params GoTestArgs) error { + if params.OutputFile == "" { + return fmt.Errorf("missing output file") + } + + fmt.Println(">> go test:", params.LogName, "Building Test Binary") + + args := []string{"test", "-c", "-o", params.OutputFile} + + if len(params.Tags) > 0 { + params := strings.Join(params.Tags, " ") + if params != "" { + args = append(args, "-tags", params) + } + } + + args = append(args, params.Packages...) + + goTestBuild := makeCommand(ctx, params.Env, "go", args...) + + err := goTestBuild.Run() + if err != nil { + return err + } + return nil +} + // GoTest invokes "go test" and reports the results to stdout. It returns an // error if there was any failure executing the tests or if there were any // test failures. diff --git a/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl b/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl index e737e21f699..a54a9edde71 100644 --- a/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl +++ b/dev-tools/packaging/templates/docker/Dockerfile.elastic-agent.tmpl @@ -56,6 +56,7 @@ RUN true && \ true # Keep this after any chown command, chown resets any applied capabilities +RUN setcap =p {{ $beatHome }}/data/elastic-agent-{{ commit_short }}/elastic-agent RUN setcap cap_net_raw,cap_setuid+p {{ $beatHome }}/data/elastic-agent-{{ commit_short }}/components/agentbeat && \ {{- if .linux_capabilities }} # Since the beat is stored at the other end of a symlink we must follow the symlink first diff --git a/go.mod b/go.mod index de44b96a280..c0d2dc7ba80 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/blakesmith/ar v0.0.0-20150311145944-8bd4349a67f2 github.com/cavaliercoder/go-rpm v0.0.0-20190131055624-7a9c54e3d83e github.com/cenkalti/backoff/v4 v4.3.0 + github.com/docker/docker v26.1.4+incompatible github.com/docker/go-units v0.5.0 github.com/dolmen-go/contextio v0.0.0-20200217195037-68fc5150bcd5 github.com/elastic/elastic-agent-autodiscover v0.8.0 @@ -63,6 +64,7 @@ require ( go.elastic.co/go-licence-detector v0.6.1 go.uber.org/zap v1.27.0 golang.org/x/crypto v0.25.0 + golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 golang.org/x/sync v0.7.0 golang.org/x/sys v0.22.0 golang.org/x/term v0.22.0 @@ -80,6 +82,7 @@ require ( k8s.io/apimachinery v0.30.1 k8s.io/client-go v0.30.1 k8s.io/utils v0.0.0-20230726121419-3b25d923346b + kernel.org/pub/linux/libs/security/libcap/cap v1.2.70 sigs.k8s.io/e2e-framework v0.4.0 sigs.k8s.io/kustomize/api v0.12.1 sigs.k8s.io/kustomize/kyaml v0.13.9 @@ -143,7 +146,6 @@ require ( github.com/cyphar/filepath-securejoin v0.2.5 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dnephin/pflag v1.0.7 // indirect - github.com/docker/docker v26.1.4+incompatible // indirect github.com/docker/go-connections v0.5.0 // indirect github.com/elastic/go-docappender/v2 v2.2.0 // indirect github.com/elastic/go-elasticsearch/v7 v7.17.10 // indirect @@ -312,7 +314,6 @@ require ( go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.starlark.net v0.0.0-20221205180719-3fd0dac74452 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/mod v0.18.0 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect @@ -324,6 +325,7 @@ require ( howett.net/plist v1.0.1 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/kubelet v0.29.3 // indirect + kernel.org/pub/linux/libs/security/libcap/psx v1.2.70 // indirect sigs.k8s.io/controller-runtime v0.18.2 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect diff --git a/go.sum b/go.sum index 36e4602269b..7da4c11bd89 100644 --- a/go.sum +++ b/go.sum @@ -2471,6 +2471,10 @@ k8s.io/kubelet v0.29.3/go.mod h1:jDiGuTkFOUynyBKzOoC1xRSWlgAZ9UPcTYeFyjr6vas= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.70 h1:QnLPkuDWWbD5C+3DUA2IUXai5TK6w2zff+MAGccqdsw= +kernel.org/pub/linux/libs/security/libcap/cap v1.2.70/go.mod h1:/iBwcj9nbLejQitYvUm9caurITQ6WyNHibJk6Q9fiS4= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.70 h1:HsB2G/rEQiYyo1bGoQqHZ/Bvd6x1rERQTNdPr1FyWjI= +kernel.org/pub/linux/libs/security/libcap/psx v1.2.70/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24= lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= diff --git a/internal/pkg/agent/cmd/common.go b/internal/pkg/agent/cmd/common.go index dd8d19d7f11..4a8582e19f3 100644 --- a/internal/pkg/agent/cmd/common.go +++ b/internal/pkg/agent/cmd/common.go @@ -37,6 +37,14 @@ func NewCommandWithArgs(args []string, streams *cli.IOStreams) *cobra.Command { cmd := &cobra.Command{ Use: "elastic-agent [subcommand]", PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + if cmd.Name() == "container" { + // need to initialize container and try to chown agent-related paths + // before tryContainerLoadPaths as this will try to read/write from + // the agent state dir which might not have proper permissions when + // running inside a container + initContainer(streams) + } + return tryContainerLoadPaths() }, } diff --git a/internal/pkg/agent/cmd/container.go b/internal/pkg/agent/cmd/container.go index eec934dad56..7386f8179bc 100644 --- a/internal/pkg/agent/cmd/container.go +++ b/internal/pkg/agent/cmd/container.go @@ -43,9 +43,10 @@ import ( const ( requestRetrySleepEnv = "KIBANA_REQUEST_RETRY_SLEEP" maxRequestRetriesEnv = "KIBANA_REQUEST_RETRY_COUNT" - defaultRequestRetrySleep = "1s" // sleep 1 sec between retries for HTTP requests - defaultMaxRequestRetries = "30" // maximum number of retries for HTTP requests - defaultStateDirectory = "/usr/share/elastic-agent/state" // directory that will hold the state data + defaultRequestRetrySleep = "1s" // sleep 1 sec between retries for HTTP requests + defaultMaxRequestRetries = "30" // maximum number of retries for HTTP requests + agentBaseDirectory = "/usr/share/elastic-agent" // directory that holds all elastic-agent related files + defaultStateDirectory = agentBaseDirectory + "/state" // directory that will hold the state data logsPathPerms = 0775 ) @@ -153,6 +154,7 @@ occurs on every start of the container set FLEET_FORCE to 1. } }, } + return &cmd } diff --git a/internal/pkg/agent/cmd/container_init_linux.go b/internal/pkg/agent/cmd/container_init_linux.go new file mode 100644 index 00000000000..fe6bf9965e3 --- /dev/null +++ b/internal/pkg/agent/cmd/container_init_linux.go @@ -0,0 +1,298 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package cmd + +// The initialization steps in this file are specifically for the elastic-agent running inside a container. +// They aim to adjust the ownership of agent-related paths to match the elastic-agent process's uid +// and elevate the process capabilities to those allowed for the container when the agent runs as non-root. +// Refer to initContainer for more details. + +import ( + "errors" + "fmt" + "io/fs" + "os" + "path/filepath" + "strings" + "syscall" + + "github.com/elastic/elastic-agent/pkg/utils" + + "kernel.org/pub/linux/libs/security/libcap/cap" + + "github.com/elastic/elastic-agent/internal/pkg/cli" +) + +type capProc interface { + GetFlag(vec cap.Flag, val cap.Value) (bool, error) + SetFlag(vec cap.Flag, enable bool, val ...cap.Value) error + SetProc() error +} + +type capBound interface { + SetVector(vec cap.Vector, raised bool, vals ...cap.Value) error + SetProc() error +} + +var ( + // for unit-testing + capBoundFunc = func() capBound { + return cap.NewIAB() + } + // for unit-testing + capProcFunc = func() capProc { + return cap.GetProc() + } +) + +func logWarning(streams *cli.IOStreams, err error) { + fmt.Fprintf(streams.Err, "Warning: %v\n", err) +} + +// initContainer applies the following container initialisation steps: +// - raises the capabilities of the Effective and Inheritable sets to match the ones in the Permitted set +// - raises the capabilities of the Ambient set to match the ones in Effective set +// - chown all agent-related paths +// +// Note that to avoid disrupting effects, any error is logged as a warning, but not returned. +func initContainer(streams *cli.IOStreams) { + isRoot, err := utils.HasRoot() + if err != nil { + logWarning(streams, err) + return + } + if !isRoot { + // if the agent runs as a non-root user, elevate the Effective capabilities to match the Bounding set. + // This is necessary because transitioning from the CRI process (uid 0) to the current process (non-zero uid) + // in Linux results in an empty Effective capabilities set. + logInfo(streams, "agent container initialisation - effective capabilities") + if err := raiseEffectiveCapabilities(); err != nil { + logWarning(streams, err) + return + } + + logInfo(streams, "agent container initialisation - ambient capabilities") + if err := raiseAmbientCapabilities(); err != nil { + logWarning(streams, err) + } + } + + // ensure all agent-related paths match the process's uid and gid to prevent access errors and + // meet required ownership checks of underlying Beats. + logInfo(streams, "agent container initialisation - chown paths") + if err := chownPaths(agentBaseDirectory); err != nil { + logWarning(streams, err) + } +} + +// raiseEffectiveCapabilities raises the capabilities of the Effective and Inheritable sets to match +// the ones in the Permitted set. Note that any capabilities that are not part of the Bounding set +// are exclude by the OS from the Permitted set. +func raiseEffectiveCapabilities() error { + procCaps := capProcFunc() + + setProc := false + + for val := cap.Value(0); val < cap.MaxBits(); val++ { + permittedHasCap, err := procCaps.GetFlag(cap.Permitted, val) + if err != nil { + return fmt.Errorf("get cap from permitted failed: %w", err) + } + if !permittedHasCap { + continue + } + + effectiveHasCap, err := procCaps.GetFlag(cap.Effective, val) + if err != nil { + return fmt.Errorf("get cap from effective failed: %w", err) + } + if !effectiveHasCap { + err = procCaps.SetFlag(cap.Effective, true, val) + if err != nil { + return fmt.Errorf("set cap to permitted failed: %w", err) + } + setProc = true + } + + inheritableHasCap, err := procCaps.GetFlag(cap.Inheritable, val) + if err != nil { + return fmt.Errorf("get cap from effective failed: %w", err) + } + if !inheritableHasCap { + err = procCaps.SetFlag(cap.Inheritable, true, val) + if err != nil { + return fmt.Errorf("set cap to inheritable failed: %w", err) + } + setProc = true + } + } + + if !setProc { + return nil + } + + if err := procCaps.SetProc(); err != nil { + return fmt.Errorf("set proc failed: %w", err) + } + + return nil +} + +// raiseAmbientCapabilities raises all capabilities present in the Effective set of the current process +// to the Ambient set excluding CAP_SETPCAP, and CAP_SETFCAP. +func raiseAmbientCapabilities() error { + var caps []cap.Value + procCaps := capProcFunc() + + effectiveHasSETPCAP := false + + for capVal := cap.Value(0); capVal < cap.MaxBits(); capVal++ { + + exists, err := procCaps.GetFlag(cap.Effective, capVal) + if err != nil { + return fmt.Errorf("failed to get proc effective flag: %w", err) + } + + if !exists { + continue + } + + if capVal == cap.SETPCAP { + effectiveHasSETPCAP = true + } + + switch capVal { + case cap.SETPCAP, cap.SETFCAP: + // don't set these as they shouldn't be required by any spawned child process + continue + default: + } + + caps = append(caps, capVal) + } + + if len(caps) == 0 { + return nil + } + + if !effectiveHasSETPCAP { + return errors.New("failed to set ambient vector: missing SETPCAP capability") + } + + iab := capBoundFunc() + for _, capVal := range caps { + if err := iab.SetVector(cap.Amb, true, capVal); err != nil { + return fmt.Errorf("failed to set ambient vector: %w", err) + } + + if err := iab.SetVector(cap.Inh, true, capVal); err != nil { + return fmt.Errorf("failed to set ambient vector: %w", err) + } + } + + return iab.SetProc() +} + +// chownPaths will chown all agent related paths to the current uid and gid. +func chownPaths(agentBaseDirectory string) error { + uid := os.Getuid() + gid := os.Getgid() + + procCaps := capProcFunc() + hasChown, err := procCaps.GetFlag(cap.Effective, cap.CHOWN) + if err != nil { + return fmt.Errorf("failed to get chown flag: %w", err) + } + if !hasChown { + hasDacOverride, err := procCaps.GetFlag(cap.Effective, cap.DAC_OVERRIDE) + if err != nil { + return fmt.Errorf("failed to get dac_override flag: %w", err) + } + if !hasDacOverride { + return errors.New("cannot chown agent paths without CAP_CHOWN or CAP_DAC_OVERRIDE capabilities") + } + } + + pathsToChown := distinctPaths{ + agentBaseDirectory: {}, + } + + pathsToChown.addPath(envWithDefault("", "LOGS_PATH")) + pathsToChown.addPath(envWithDefault("", "STATE_PATH")) + pathsToChown.addPath(envWithDefault("", "CONFIG_PATH")) + pathsToChown.addPath(envWithDefault("", "DATA_PATH")) + pathsToChown.addPath(envWithDefault("", "HOME_PATH")) + return pathsToChown.chown(uid, gid) +} + +// distinctPaths represents a set of paths that do not overlap. +type distinctPaths map[string]struct{} + +// addPath will add the given path to the set if a parent path is not already present. +// Also, if the given path is the parent of existing entries these will be removed. +func (u distinctPaths) addPath(path string) { + if u == nil || path == "" { + return + } + for entry := range u { + if strings.HasPrefix(path, entry) { + // parent included in paths + return + } + + if strings.HasPrefix(entry, path) { + // entry is a child of path to add so remove it + delete(u, entry) + } + } + + u[path] = struct{}{} +} + +// chown will chown all paths in the set to the given uid and gid. +func (u distinctPaths) chown(uid int, gid int) error { + if u == nil { + return nil + } + for entry := range u { + err := filepath.WalkDir(entry, func(walkPath string, d fs.DirEntry, err error) error { + if err != nil { + return fmt.Errorf("failed to walk path %s: %w", walkPath, err) + } + + info, err := d.Info() + if err != nil { + return fmt.Errorf("failed to get info of path %s: %w", walkPath, err) + } + + sysInfo, ok := info.Sys().(*syscall.Stat_t) + if !ok { + return nil + } + + if sysInfo.Gid == uint32(gid) && sysInfo.Uid == uint32(uid) { + // already owned + return nil + } + + if err = os.Chown(walkPath, uid, gid); err != nil { + return fmt.Errorf("failed to chown path %s: %w", walkPath, err) + } + + if info.Mode()&fs.ModeSymlink != 0 { + if err = os.Lchown(walkPath, uid, gid); err != nil { + return fmt.Errorf("failed to chown path %s: %w", walkPath, err) + } + } + + return nil + }) + if err != nil { + return err + } + } + + return nil +} diff --git a/internal/pkg/agent/cmd/container_init_other.go b/internal/pkg/agent/cmd/container_init_other.go new file mode 100644 index 00000000000..caa888cbdbf --- /dev/null +++ b/internal/pkg/agent/cmd/container_init_other.go @@ -0,0 +1,13 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +//go:build !linux + +package cmd + +import ( + "github.com/elastic/elastic-agent/internal/pkg/cli" +) + +func initContainer(_ *cli.IOStreams) {} diff --git a/internal/pkg/agent/cmd/container_init_test.go b/internal/pkg/agent/cmd/container_init_test.go new file mode 100644 index 00000000000..b8dd3b8edb7 --- /dev/null +++ b/internal/pkg/agent/cmd/container_init_test.go @@ -0,0 +1,394 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +//go:build linux + +package cmd + +import ( + "errors" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" + + "golang.org/x/exp/maps" + "kernel.org/pub/linux/libs/security/libcap/cap" +) + +func Test_distinctPaths(t *testing.T) { + firstParentDir := t.TempDir() + secondParentDir := t.TempDir() + + childDir := filepath.Join(secondParentDir, "child") + + childChildDir := filepath.Join(childDir, "child") + + pathsToChown := distinctPaths{} + pathsToChown.addPath(childDir) + pathsToChown.addPath(secondParentDir) + pathsToChown.addPath(childChildDir) + pathsToChown.addPath(firstParentDir) + + require.EqualValues(t, distinctPaths{firstParentDir: {}, secondParentDir: {}}, pathsToChown) + + err := pathsToChown.chown(os.Getuid(), os.Getgid()) + require.NoError(t, err) +} + +func Test_chownPaths(t *testing.T) { + t.Cleanup(func() { + capProcFunc = func() capProc { + return cap.GetProc() + } + }) + + tc := []struct { + name string + mockedProcCaps *mockCapProc + expectErr bool + expectedCaps []cap.Value + }{ + { + name: "has CHOWN capability", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{cap.CHOWN: {}}, + }, + expectErr: false, + }, + { + name: "has DAC_OVERRIDE capability", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{cap.DAC_OVERRIDE: {}}, + }, + expectErr: false, + }, + { + name: "has neither CHOWN nor DAC_OVERRIDE capabilities", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{cap.BPF: {}, cap.SETFCAP: {}}, + }, + expectErr: true, + }, + { + name: "get flag error", + mockedProcCaps: &mockCapProc{ + getFlagErr: errors.New("error"), + }, + expectErr: true, + }, + } + + for _, tt := range tc { + t.Run(tt.name, func(t *testing.T) { + capProcFunc = func() capProc { + return tt.mockedProcCaps + } + + err := chownPaths(t.TempDir()) + if tt.expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + } + }) + } +} + +func Test_raiseEffectiveCapabilities(t *testing.T) { + t.Cleanup(func() { + capProcFunc = func() capProc { + return cap.GetProc() + } + }) + + tc := []struct { + name string + mockedProcCaps *mockCapProc + expectErr bool + expectedCaps []cap.Value + }{ + { + name: "set effective and inheritable", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{}, + inheritableCaps: map[cap.Value]struct{}{}, + permittedCaps: map[cap.Value]struct{}{cap.CHOWN: {}, cap.BPF: {}}, + }, + expectedCaps: []cap.Value{cap.CHOWN, cap.BPF}, + expectErr: false, + }, + { + name: "no caps to set", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{}, + inheritableCaps: map[cap.Value]struct{}{}, + permittedCaps: map[cap.Value]struct{}{}, + setProcErr: errors.New("error"), + }, + expectedCaps: []cap.Value{}, + expectErr: false, + }, + { + name: "no caps to set - already set", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{cap.CHOWN: {}, cap.BPF: {}}, + inheritableCaps: map[cap.Value]struct{}{cap.CHOWN: {}, cap.BPF: {}}, + permittedCaps: map[cap.Value]struct{}{cap.CHOWN: {}, cap.BPF: {}}, + setProcErr: errors.New("error"), + }, + expectedCaps: []cap.Value{cap.CHOWN, cap.BPF}, + expectErr: false, + }, + { + name: "set effective and inheritable with different caps", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{cap.CHOWN: {}}, + inheritableCaps: map[cap.Value]struct{}{cap.BPF: {}}, + permittedCaps: map[cap.Value]struct{}{cap.CHOWN: {}, cap.BPF: {}}, + }, + expectedCaps: []cap.Value{cap.CHOWN, cap.BPF}, + expectErr: false, + }, + { + name: "set effective and inheritable get flag error", + mockedProcCaps: &mockCapProc{ + getFlagErr: errors.New("error"), + }, + expectErr: true, + }, + { + name: "set effective and inheritable set flag error", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{}, + inheritableCaps: map[cap.Value]struct{}{}, + permittedCaps: map[cap.Value]struct{}{cap.CHOWN: {}, cap.BPF: {}}, + setFlagErr: errors.New("error"), + }, + expectErr: true, + }, + { + name: "set effective and inheritable set proc error", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{}, + inheritableCaps: map[cap.Value]struct{}{}, + permittedCaps: map[cap.Value]struct{}{cap.CHOWN: {}, cap.BPF: {}}, + setProcErr: errors.New("error"), + }, + expectErr: true, + }, + } + + for _, tt := range tc { + t.Run(tt.name, func(t *testing.T) { + capProcFunc = func() capProc { + return tt.mockedProcCaps + } + + err := raiseEffectiveCapabilities() + if tt.expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.ElementsMatch(t, tt.expectedCaps, maps.Keys(tt.mockedProcCaps.effectiveCaps)) + require.ElementsMatch(t, tt.expectedCaps, maps.Keys(tt.mockedProcCaps.inheritableCaps)) + } + }) + } +} + +func Test_raiseAmbientCapabilities(t *testing.T) { + t.Cleanup(func() { + capProcFunc = func() capProc { + return cap.GetProc() + } + capBoundFunc = func() capBound { + return cap.NewIAB() + } + }) + + tc := []struct { + name string + mockedProcCaps *mockCapProc + mockedBoundCaps *mockCapBound + expectErr bool + expectedAmbientCaps []cap.Value + }{ + { + name: "no ambient caps to set due to cap exclusion", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{cap.SETPCAP: {}, cap.SETFCAP: {}}, + }, + mockedBoundCaps: &mockCapBound{}, + expectErr: false, + expectedAmbientCaps: []cap.Value{}, + }, + { + name: "no ambient caps to set", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{}, + }, + mockedBoundCaps: &mockCapBound{}, + expectErr: false, + expectedAmbientCaps: []cap.Value{}, + }, + { + name: "ambient caps to set", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{cap.SETPCAP: {}, cap.SETFCAP: {}, cap.CHOWN: {}, cap.BPF: {}}, + }, + mockedBoundCaps: &mockCapBound{ + ambientCaps: map[cap.Value]struct{}{}, + }, + expectErr: false, + expectedAmbientCaps: []cap.Value{ + cap.CHOWN, cap.BPF, + }, + }, + { + name: "ambient caps get flag err", + mockedProcCaps: &mockCapProc{ + getFlagErr: errors.New("error"), + }, + expectErr: true, + }, + { + name: "ambient caps set vector err", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{cap.SETPCAP: {}, cap.SETFCAP: {}, cap.CHOWN: {}, cap.BPF: {}}, + }, + mockedBoundCaps: &mockCapBound{ + setVectorErr: errors.New("error"), + }, + expectErr: true, + }, + { + name: "ambient caps set proc err", + mockedProcCaps: &mockCapProc{ + effectiveCaps: map[cap.Value]struct{}{cap.SETPCAP: {}, cap.SETFCAP: {}, cap.CHOWN: {}, cap.BPF: {}}, + }, + mockedBoundCaps: &mockCapBound{ + ambientCaps: map[cap.Value]struct{}{}, + setProcErr: errors.New("error"), + }, + expectErr: true, + }, + } + + for _, tt := range tc { + t.Run(tt.name, func(t *testing.T) { + capProcFunc = func() capProc { + return tt.mockedProcCaps + } + capBoundFunc = func() capBound { + return tt.mockedBoundCaps + } + + err := raiseAmbientCapabilities() + if tt.expectErr { + require.Error(t, err) + } else { + require.NoError(t, err) + require.ElementsMatch(t, tt.expectedAmbientCaps, maps.Keys(tt.mockedBoundCaps.ambientCaps)) + } + }) + } +} + +var _ capProc = &mockCapProc{} + +type mockCapProc struct { + effectiveCaps map[cap.Value]struct{} + inheritableCaps map[cap.Value]struct{} + permittedCaps map[cap.Value]struct{} + setFlagErr error + getFlagErr error + setProcErr error +} + +func (m *mockCapProc) GetFlag(vec cap.Flag, val cap.Value) (bool, error) { + if m.getFlagErr != nil { + return false, m.getFlagErr + } + + switch vec { + case cap.Effective: + _, ok := m.effectiveCaps[val] + return ok, nil + case cap.Inheritable: + _, ok := m.inheritableCaps[val] + return ok, nil + case cap.Permitted: + _, ok := m.permittedCaps[val] + return ok, nil + default: + return false, nil + } +} +func (m *mockCapProc) SetFlag(vec cap.Flag, enable bool, val ...cap.Value) error { + if m.setFlagErr != nil { + return m.setFlagErr + } + + var targetMap map[cap.Value]struct{} + switch vec { + case cap.Effective: + targetMap = m.effectiveCaps + case cap.Inheritable: + targetMap = m.inheritableCaps + case cap.Permitted: + targetMap = m.permittedCaps + default: + return nil + } + + for _, v := range val { + if enable { + targetMap[v] = struct{}{} + } else { + delete(targetMap, v) + } + } + return nil +} + +func (m *mockCapProc) SetProc() error { + return m.setProcErr +} + +var _ capBound = &mockCapBound{} + +type mockCapBound struct { + ambientCaps map[cap.Value]struct{} + setVectorErr error + setProcErr error +} + +func (m *mockCapBound) SetVector(vec cap.Vector, raised bool, vals ...cap.Value) error { + if m.setVectorErr != nil { + return m.setVectorErr + } + + var targetMap map[cap.Value]struct{} + switch vec { + case cap.Amb: + targetMap = m.ambientCaps + default: + return nil + } + + for _, v := range vals { + if raised { + targetMap[v] = struct{}{} + } else { + delete(targetMap, v) + } + } + return nil +} + +func (m *mockCapBound) SetProc() error { + return m.setProcErr +} diff --git a/pkg/testing/kubernetes/image.go b/pkg/testing/kubernetes/image.go new file mode 100644 index 00000000000..83b350609f2 --- /dev/null +++ b/pkg/testing/kubernetes/image.go @@ -0,0 +1,246 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +package kubernetes + +import ( + "archive/tar" + "bufio" + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "os" + "path/filepath" + "strings" + + devtools "github.com/elastic/elastic-agent/dev-tools/mage" + "github.com/elastic/elastic-agent/pkg/testing/runner" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/client" +) + +type DockerConfig struct { + CurrentContext string `json:"currentContext"` +} + +type DockerContext struct { + Name string `json:"Name"` + Metadata map[string]interface{} `json:"Metadata"` + Endpoints map[string]Endpoint `json:"Endpoints"` + Storage map[string]interface{} `json:"Storage"` + TLS bool `json:"TLS"` +} + +type DockerBuildOutput struct { + Stream string `json:"stream"` + Aux struct { + ID string `json:"ID"` + } `json:"aux"` +} + +type Endpoint struct { + Host string `json:"Host"` +} + +// AddK8STestsToImage compiles and adds the k8s-inner-tests binary to the given image +func AddK8STestsToImage(ctx context.Context, logger runner.Logger, baseImage string, arch string) (string, error) { + // compile k8s test with tag kubernetes_inner + buildBase, err := filepath.Abs("build") + if err != nil { + return "", err + } + + testBinary := filepath.Join(buildBase, "k8s-inner-tests") + + params := devtools.GoTestArgs{ + LogName: "k8s-inner-tests", + Race: false, + Packages: []string{"./testing/kubernetes_inner/..."}, + Tags: []string{"kubernetes_inner"}, + OutputFile: testBinary, + Env: map[string]string{ + "GOOS": "linux", + "GOARCH": arch, + "CGO_ENABLED": "0", + }, + } + + if err := devtools.GoTestBuild(ctx, params); err != nil { + return "", err + } + + cli, err := getDockerClient() + if err != nil { + return "", err + } + + // dockerfile to just copy the tests binary + dockerfile := fmt.Sprintf(` + FROM %s + COPY testsBinary /usr/share/elastic-agent/k8s-inner-tests + `, baseImage) + + // Create a tar archive with the Dockerfile and the binary + var buf bytes.Buffer + tw := tar.NewWriter(&buf) + + // Add Dockerfile to tar + err = tw.WriteHeader(&tar.Header{ + Name: "Dockerfile", + Size: int64(len(dockerfile)), + }) + if err != nil { + return "", err + } + _, err = tw.Write([]byte(dockerfile)) + if err != nil { + return "", err + } + + // Add binary to tar + binaryFile, err := os.Open(testBinary) + if err != nil { + return "", err + } + defer binaryFile.Close() + + info, err := binaryFile.Stat() + if err != nil { + return "", err + } + + err = tw.WriteHeader(&tar.Header{ + Name: "testsBinary", + Mode: 0777, + Size: info.Size(), + }) + if err != nil { + return "", err + } + _, err = io.Copy(tw, binaryFile) + if err != nil { + return "", err + } + + err = tw.Close() + if err != nil { + return "", err + } + + outputImage := baseImage + "-tests" + + // Build the image + imageBuildResponse, err := cli.ImageBuild(ctx, &buf, types.ImageBuildOptions{ + Tags: []string{outputImage}, + Dockerfile: "Dockerfile", + Remove: true, + }) + if err != nil { + return "", err + } + defer imageBuildResponse.Body.Close() + + scanner := bufio.NewScanner(imageBuildResponse.Body) + for scanner.Scan() { + line := scanner.Text() + var output DockerBuildOutput + if err := json.Unmarshal([]byte(line), &output); err != nil { + return "", fmt.Errorf("error at parsing JSON: %w", err) + } + + if output.Stream != "" { + if out := strings.TrimRight(output.Stream, "\n"); out != "" { + logger.Logf(out) + } + } + } + + if err := scanner.Err(); err != nil { + return "", err + } + + return outputImage, nil +} + +// getDockerClient returns an instance of the Docker client. It first checks +// if there is a current context inside $/.docker/config.json and instantiates +// a client based on it. Otherwise, it fallbacks to a docker client with values +// from environment variables. +func getDockerClient() (*client.Client, error) { + + envClient := func() (*client.Client, error) { + return client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + } + + type DockerConfig struct { + CurrentContext string `json:"currentContext"` + } + + configFile := filepath.Join(os.Getenv("HOME"), ".docker", "config.json") + file, err := os.Open(configFile) + if err != nil { + if os.IsNotExist(err) { + return envClient() + } + return nil, err + } + defer file.Close() + + var config DockerConfig + decoder := json.NewDecoder(file) + err = decoder.Decode(&config) + if err != nil { + return nil, err + } + + if config.CurrentContext == "" { + return envClient() + } + + contextDir := filepath.Join(os.Getenv("HOME"), ".docker", "contexts", "meta") + files, err := os.ReadDir(contextDir) + if err != nil { + if os.IsNotExist(err) { + return envClient() + } + return nil, fmt.Errorf("unable to read Docker contexts directory: %w", err) + } + + for _, f := range files { + if f.IsDir() { + metaFile := filepath.Join(contextDir, f.Name(), "meta.json") + if _, err := os.Stat(metaFile); err == nil { + if os.IsNotExist(err) { + return envClient() + } + var dockerContext DockerContext + content, err := os.ReadFile(metaFile) + if err != nil { + return nil, fmt.Errorf("unable to read Docker context meta file: %w", err) + } + if err := json.Unmarshal(content, &dockerContext); err != nil { + return nil, fmt.Errorf("unable to parse Docker context meta file: %w", err) + } + if dockerContext.Name != config.CurrentContext { + continue + } + + endpoint, ok := dockerContext.Endpoints["docker"] + if !ok { + return nil, fmt.Errorf("docker endpoint not found in context") + } + + return client.NewClientWithOpts( + client.WithHost(endpoint.Host), + client.WithAPIVersionNegotiation(), + ) + } + } + } + + return envClient() +} diff --git a/pkg/testing/kubernetes/kind/provisioner.go b/pkg/testing/kubernetes/kind/provisioner.go index b4d454768de..f5601b3f0e8 100644 --- a/pkg/testing/kubernetes/kind/provisioner.go +++ b/pkg/testing/kubernetes/kind/provisioner.go @@ -16,6 +16,7 @@ import ( "strings" "github.com/elastic/elastic-agent/pkg/testing/define" + "github.com/elastic/elastic-agent/pkg/testing/kubernetes" "github.com/elastic/elastic-agent/pkg/testing/runner" v1 "k8s.io/api/core/v1" @@ -83,6 +84,12 @@ func (p *provisioner) Supported(batch define.OS) bool { func (p *provisioner) Provision(ctx context.Context, cfg runner.Config, batches []runner.OSBatch) ([]runner.Instance, error) { + agentImageWithoutTests := fmt.Sprintf("docker.elastic.co/beats/elastic-agent-complete:%s", cfg.AgentVersion) + agentImage, err := kubernetes.AddK8STestsToImage(ctx, p.logger, agentImageWithoutTests, runtime.GOARCH) + if err != nil { + return nil, err + } + versionsMap := make(map[string]string) for _, batch := range batches { @@ -141,7 +148,6 @@ func (p *provisioner) Provision(ctx context.Context, cfg runner.Config, batches return nil, err } - agentImage := fmt.Sprintf("docker.elastic.co/beats/elastic-agent-complete:%s", cfg.AgentVersion) if err := p.LoadImage(ctx, instanceName, agentImage); err != nil { return nil, err } diff --git a/testing/integration/kubernetes_agent_standalone_test.go b/testing/integration/kubernetes_agent_standalone_test.go index 41f06b28cc8..e607e3065e5 100644 --- a/testing/integration/kubernetes_agent_standalone_test.go +++ b/testing/integration/kubernetes_agent_standalone_test.go @@ -8,19 +8,26 @@ import ( "bufio" "bytes" "context" + "crypto/sha256" + "encoding/base64" + "encoding/json" "errors" "fmt" "io" "os" "path/filepath" + "regexp" + "strings" "testing" "time" "github.com/stretchr/testify/require" "github.com/elastic/elastic-agent/pkg/testing/define" + "github.com/elastic/go-elasticsearch/v8" appsv1 "k8s.io/api/apps/v1" + batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -36,6 +43,8 @@ import ( const agentK8SKustomize = "../../deploy/kubernetes/elastic-agent-kustomize/default/elastic-agent-standalone" +var noSpecialCharsRegexp = regexp.MustCompile("[^a-zA-Z0-9]+") + func TestKubernetesAgentStandalone(t *testing.T) { info := define.Require(t, define.Requirements{ Stack: &define.Stack{}, @@ -48,96 +57,186 @@ func TestKubernetesAgentStandalone(t *testing.T) { }) agentImage := os.Getenv("AGENT_IMAGE") - require.NotEmpty(t, agentImage) + require.NotEmpty(t, agentImage, "AGENT_IMAGE must be set") client, err := info.KubeClient() require.NoError(t, err) require.NotNil(t, client) testLogsBasePath := os.Getenv("K8S_TESTS_POD_LOGS_BASE") - require.NotEmpty(t, testLogsBasePath) + require.NotEmpty(t, testLogsBasePath, "K8S_TESTS_POD_LOGS_BASE must be set") - ctx := context.Background() + err = os.MkdirAll(filepath.Join(testLogsBasePath, t.Name()), 0755) + require.NoError(t, err, "failed to create test logs directory") namespace := info.Namespace - // Create a file system pointing to the kustomize directory - fSys := filesys.MakeFsOnDisk() - - // Create a kustomizer - k := krusty.MakeKustomizer(krusty.MakeDefaultOptions()) + esHost := os.Getenv("ELASTICSEARCH_HOST") + require.NotEmpty(t, esHost, "ELASTICSEARCH_HOST must be set") + + esAPIKey, err := generateESAPIKey(info.ESClient, namespace) + require.NoError(t, err, "failed to generate ES API key") + require.NotEmpty(t, esAPIKey, "failed to generate ES API key") + + renderedManifest, err := renderKustomize(agentK8SKustomize) + require.NoError(t, err, "failed to render kustomize") + + testCases := []struct { + name string + runUser *int64 + runGroup *int64 + capabilitiesDrop []corev1.Capability + capabilitiesAdd []corev1.Capability + runK8SInnerTests bool + }{ + { + "default deployment - rootful agent", + nil, + nil, + nil, + nil, + false, + }, + { + "drop ALL capabilities - rootful agent", + int64Ptr(0), + nil, + []corev1.Capability{"ALL"}, + []corev1.Capability{}, + false, + }, + { + "drop ALL add CHOWN, SETPCAP capabilities - rootful agent", + int64Ptr(0), + nil, + []corev1.Capability{"ALL"}, + []corev1.Capability{"CHOWN", "SETPCAP"}, + true, + }, + { + "drop ALL add CHOWN, SETPCAP capabilities - rootless agent", + int64Ptr(1000), // elastic-agent uid + nil, + []corev1.Capability{"ALL"}, + []corev1.Capability{"CHOWN", "SETPCAP"}, + true, + }, + { + "drop ALL add CHOWN, SETPCAP capabilities - rootless agent random uid:gid", + int64Ptr(500), + int64Ptr(500), + []corev1.Capability{"ALL"}, + []corev1.Capability{"CHOWN", "SETPCAP", "DAC_READ_SEARCH"}, + true, + }, + } - // Run the kustomizer on the given directory - resMap, err := k.Run(fSys, agentK8SKustomize) - require.NoError(t, err) + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + hasher := sha256.New() + hasher.Write([]byte(tc.name)) + testNamespace := strings.ToLower(base64.URLEncoding.EncodeToString(hasher.Sum(nil))) + testNamespace = noSpecialCharsRegexp.ReplaceAllString(testNamespace, "") + + k8sObjects, err := yamlToK8SObjects(bufio.NewReader(bytes.NewReader(renderedManifest))) + require.NoError(t, err, "failed to convert yaml to k8s objects") + + adjustK8SAgentManifests(k8sObjects, testNamespace, "elastic-agent-standalone", + func(container *corev1.Container) { + // set agent image + container.Image = agentImage + // set ImagePullPolicy to "Never" to avoid pulling the image + // as the image is already loaded by the kubernetes provisioner + container.ImagePullPolicy = "Never" + + if tc.capabilitiesDrop != nil || tc.capabilitiesAdd != nil || tc.runUser != nil || tc.runGroup != nil { + // set security context + container.SecurityContext = &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Drop: tc.capabilitiesDrop, + Add: tc.capabilitiesAdd, + }, + RunAsUser: tc.runUser, + RunAsGroup: tc.runGroup, + } + + } + // set Elasticsearch host and API key + for idx, env := range container.Env { + if env.Name == "ES_HOST" { + container.Env[idx].Value = esHost + container.Env[idx].ValueFrom = nil + } + if env.Name == "API_KEY" { + container.Env[idx].Value = esAPIKey + container.Env[idx].ValueFrom = nil + } + } + }, + func(pod *corev1.PodSpec) { + for volumeIdx, volume := range pod.Volumes { + // need to update the volume path of the state directory + // to match the test namespace + if volume.Name == "elastic-agent-state" { + hostPathType := corev1.HostPathDirectoryOrCreate + pod.Volumes[volumeIdx].VolumeSource.HostPath = &corev1.HostPathVolumeSource{ + Type: &hostPathType, + Path: fmt.Sprintf("/var/lib/elastic-agent-standalone/%s/state", testNamespace), + } + } + } + }) + + ctx := context.Background() + + deployK8SAgent(t, ctx, client, k8sObjects, testNamespace, tc.runK8SInnerTests, testLogsBasePath) + }) + } - // Convert the result to YAML - renderedManifest, err := resMap.AsYaml() - require.NoError(t, err) +} - decoder := newYamlReader() - objects, err := decoder.ToObjects(bufio.NewReader(bytes.NewReader(renderedManifest))) - require.NoError(t, err) +// deployK8SAgent is a helper function to deploy the elastic-agent in k8s and invoke the inner k8s tests if +// runK8SInnerTests is true +func deployK8SAgent(t *testing.T, ctx context.Context, client klient.Client, objects []k8s.Object, namespace string, + runInnerK8STests bool, testLogsBasePath string) { - k8sNamespaceObj := &corev1.Namespace{ + objects = append([]k8s.Object{&corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ Name: namespace, }, - } + }}, objects...) + t.Cleanup(func() { if t.Failed() { dumpLogs(t, ctx, client, namespace, testLogsBasePath) } - _ = client.Resources().Delete(ctx, k8sNamespaceObj) - for _, obj := range objects { - _ = client.Resources(namespace).Delete(ctx, obj) - } - }) - - err = client.Resources().Create(ctx, k8sNamespaceObj) - require.NoError(t, err) - // Update the agent image and image pull policy as it is already loaded in kind cluster - for _, obj := range objects { - switch objWithType := obj.(type) { - case *appsv1.DaemonSet: - for idx, container := range objWithType.Spec.Template.Spec.Containers { - if container.Name == "elastic-agent-standalone" { - objWithType.Spec.Template.Spec.Containers[idx].Image = agentImage - objWithType.Spec.Template.Spec.Containers[idx].ImagePullPolicy = "Never" - } - } - case *appsv1.StatefulSet: - for idx, container := range objWithType.Spec.Template.Spec.Containers { - if container.Name == "elastic-agent-standalone" { - objWithType.Spec.Template.Spec.Containers[idx].Image = agentImage - objWithType.Spec.Template.Spec.Containers[idx].ImagePullPolicy = "Never" - } - } - case *appsv1.Deployment: - for idx, container := range objWithType.Spec.Template.Spec.Containers { - if container.Name == "elastic-agent-standalone" { - objWithType.Spec.Template.Spec.Containers[idx].Image = agentImage - objWithType.Spec.Template.Spec.Containers[idx].ImagePullPolicy = "Never" - } - } - } - } + // need to delete all k8s objects and wait for it as elastic-agent + // in k8s creates cluster-wide roles and having multiple of them at + // the same time isn't allowed + deleteK8SObjects(t, ctx, client, objects, true) + }) // Create the objects for _, obj := range objects { obj.SetNamespace(namespace) - err = client.Resources(namespace).Create(ctx, obj) - require.NoError(t, err) + err := client.Resources(namespace).Create(ctx, obj) + require.NoError(t, err, fmt.Sprintf("failed to create object %s", obj.GetName())) } + var agentPodName string // Wait for pods to be ready require.Eventually(t, func() bool { podList := &corev1.PodList{} err := client.Resources(namespace).List(ctx, podList) - require.NoError(t, err) + require.NoError(t, err, fmt.Sprintf("failed to list pods in namespace %s", namespace)) for _, pod := range podList.Items { + if agentPodName == "" && strings.HasPrefix(pod.GetName(), "elastic-agent-standalone") { + agentPodName = pod.Name + } + for _, containerStatus := range pod.Status.ContainerStatuses { if containerStatus.RestartCount > 0 { return false @@ -156,14 +255,52 @@ func TestKubernetesAgentStandalone(t *testing.T) { } return true - }, time.Second*100, time.Second*1, "Timed out waiting for pods to be ready") + }, time.Second*100, time.Second*1, fmt.Sprintf("pods in namespace %s never became ready", namespace)) + + require.NotEmpty(t, agentPodName, "agent pod name is empty") + + command := []string{"elastic-agent", "status"} + var stdout, stderr bytes.Buffer + var agentHealthyErr error + // we will wait maximum 60 seconds for the agent to report healthy + for i := 0; i < 60; i++ { + stdout.Reset() + stderr.Reset() + agentHealthyErr = client.Resources().ExecInPod(ctx, namespace, agentPodName, "elastic-agent-standalone", command, &stdout, &stderr) + if agentHealthyErr == nil { + break + } + time.Sleep(time.Second * 1) + } + + if agentHealthyErr != nil { + t.Errorf("elastic-agent never reported healthy: %v", agentHealthyErr) + t.Logf("stdout: %s\n", stdout.String()) + t.Logf("stderr: %s\n", stderr.String()) + t.FailNow() + return + } + + stdout.Reset() + stderr.Reset() + + if runInnerK8STests { + err := client.Resources().ExecInPod(ctx, namespace, agentPodName, "elastic-agent-standalone", + []string{"/usr/share/elastic-agent/k8s-inner-tests", "-test.v"}, &stdout, &stderr) + t.Log(stdout.String()) + if err != nil { + t.Log(stderr.String()) + } + require.NoError(t, err, "error at k8s inner tests execution") + } } +// dumpLogs dumps the logs of all pods in the given namespace to the given target directory func dumpLogs(t *testing.T, ctx context.Context, client klient.Client, namespace string, targetDir string) { podList := &corev1.PodList{} - clientset, err := kubernetes.NewForConfig(client.RESTConfig()) + clientSet, err := kubernetes.NewForConfig(client.RESTConfig()) if err != nil { t.Logf("Error creating clientset: %v\n", err) return @@ -193,7 +330,7 @@ func dumpLogs(t *testing.T, ctx context.Context, client klient.Client, namespace continue } - req := clientset.CoreV1().Pods(namespace).GetLogs(pod.Name, &corev1.PodLogOptions{ + req := clientSet.CoreV1().Pods(namespace).GetLogs(pod.Name, &corev1.PodLogOptions{ Container: container.Name, Previous: previous, }) @@ -215,12 +352,63 @@ func dumpLogs(t *testing.T, ctx context.Context, client klient.Client, namespace } } -// YAMLDecoder converts YAML bytes into test.Builder instances. -type YAMLDecoder struct { - decoder runtime.Decoder +// adjustK8SAgentManifests adjusts the namespace of given k8s objects and calls the given callbacks for the containers and the pod +func adjustK8SAgentManifests(objects []k8s.Object, namespace string, containerName string, cbContainer func(container *corev1.Container), cbPod func(pod *corev1.PodSpec)) { + // Update the agent image and image pull policy as it is already loaded in kind cluster + for _, obj := range objects { + obj.SetNamespace(namespace) + var podSpec *corev1.PodSpec + switch objWithType := obj.(type) { + case *appsv1.DaemonSet: + podSpec = &objWithType.Spec.Template.Spec + case *appsv1.StatefulSet: + podSpec = &objWithType.Spec.Template.Spec + case *appsv1.Deployment: + podSpec = &objWithType.Spec.Template.Spec + case *appsv1.ReplicaSet: + podSpec = &objWithType.Spec.Template.Spec + case *batchv1.Job: + podSpec = &objWithType.Spec.Template.Spec + case *batchv1.CronJob: + podSpec = &objWithType.Spec.JobTemplate.Spec.Template.Spec + case *rbacv1.ClusterRoleBinding: + for idx, subject := range objWithType.Subjects { + if strings.HasPrefix(subject.Name, "elastic-agent") { + objWithType.Subjects[idx].Namespace = namespace + } + } + continue + case *rbacv1.RoleBinding: + for idx, subject := range objWithType.Subjects { + if strings.HasPrefix(subject.Name, "elastic-agent") { + objWithType.Subjects[idx].Namespace = namespace + } + } + continue + default: + continue + } + + for idx, container := range podSpec.Containers { + if container.Name != containerName { + continue + } + if cbContainer != nil { + cbContainer(&podSpec.Containers[idx]) + } + + if cbPod != nil { + cbPod(podSpec) + } + } + + } } -func newYamlReader() *YAMLDecoder { +// yamlToK8SObjects converts yaml to k8s objects +func yamlToK8SObjects(reader *bufio.Reader) ([]k8s.Object, error) { + var objects []k8s.Object + scheme := runtime.NewScheme() scheme.AddKnownTypes(rbacv1.SchemeGroupVersion, &rbacv1.ClusterRoleBinding{}, &rbacv1.ClusterRoleBindingList{}) scheme.AddKnownTypes(rbacv1.SchemeGroupVersion, &rbacv1.ClusterRole{}, &rbacv1.ClusterRoleList{}) @@ -234,12 +422,6 @@ func newYamlReader() *YAMLDecoder { scheme.AddKnownTypes(corev1.SchemeGroupVersion, &corev1.Secret{}, &corev1.ConfigMap{}) decoder := serializer.NewCodecFactory(scheme).UniversalDeserializer() - return &YAMLDecoder{decoder: decoder} -} - -func (yd *YAMLDecoder) ToObjects(reader *bufio.Reader) ([]k8s.Object, error) { - var objects []k8s.Object - yamlReader := yaml.NewYAMLReader(reader) for { yamlBytes, err := yamlReader.Read() @@ -249,7 +431,7 @@ func (yd *YAMLDecoder) ToObjects(reader *bufio.Reader) ([]k8s.Object, error) { } return nil, fmt.Errorf("failed to read YAML: %w", err) } - obj, _, err := yd.decoder.Decode(yamlBytes, nil, nil) + obj, _, err := decoder.Decode(yamlBytes, nil, nil) if err != nil { return nil, fmt.Errorf("failed to decode YAML: %w", err) } @@ -264,3 +446,99 @@ func (yd *YAMLDecoder) ToObjects(reader *bufio.Reader) ([]k8s.Object, error) { return objects, nil } + +// renderKustomize renders the given kustomize directory to YAML +func renderKustomize(kustomizePath string) ([]byte, error) { + // Create a file system pointing to the kustomize directory + fSys := filesys.MakeFsOnDisk() + + // Create a kustomizer + k := krusty.MakeKustomizer(krusty.MakeDefaultOptions()) + + // Run the kustomizer on the given directory + resMap, err := k.Run(fSys, kustomizePath) + if err != nil { + return nil, err + } + + // Convert the result to YAML + renderedManifest, err := resMap.AsYaml() + if err != nil { + return nil, err + } + + return renderedManifest, nil +} + +// generateESAPIKey generates an API key for the given Elasticsearch. +func generateESAPIKey(esClient *elasticsearch.Client, keyName string) (string, error) { + apiKeyReqBody := fmt.Sprintf(`{ + "name": "%s", + "expiration": "1d" + }`, keyName) + + resp, err := esClient.Security.CreateAPIKey(strings.NewReader(apiKeyReqBody)) + if err != nil { + return "", err + } + defer resp.Body.Close() + + response := make(map[string]interface{}) + err = json.NewDecoder(resp.Body).Decode(&response) + if err != nil { + return "", err + } + + keyToken := response["api_key"].(string) + if keyToken == "" { + return "", fmt.Errorf("key token is empty") + } + + keyID := response["id"].(string) + if keyID == "" { + return "", fmt.Errorf("key ID is empty") + } + + return fmt.Sprintf("%s:%s", keyID, keyToken), nil +} + +// deleteK8SObjects deletes the given k8s objects and waits for them to be deleted if wait is true. +func deleteK8SObjects(t *testing.T, ctx context.Context, client klient.Client, objects []k8s.Object, wait bool) { + for _, obj := range objects { + _ = client.Resources().Delete(ctx, obj) + } + + if !wait { + return + } + + timeoutCtx, timeoutCancel := context.WithTimeout(ctx, 10*time.Second) + defer timeoutCancel() + + for _, obj := range objects { + if timeoutCtx.Err() != nil { + break + } + + for i := 0; i < 10; i++ { + if timeoutCtx.Err() != nil { + break + } + + err := client.Resources().Get(timeoutCtx, obj.GetName(), obj.GetNamespace(), obj) + if err != nil { + break + } + time.Sleep(500 * time.Millisecond) + } + } + + if timeoutCtx.Err() != nil { + t.Log("Timeout waiting for k8s objects to be deleted") + } +} + +func int64Ptr(val int64) *int64 { + valPtr := val + return &valPtr +} diff --git a/testing/kubernetes_inner/agent_paths_ownership_test.go b/testing/kubernetes_inner/agent_paths_ownership_test.go new file mode 100644 index 00000000000..c0690ccfec0 --- /dev/null +++ b/testing/kubernetes_inner/agent_paths_ownership_test.go @@ -0,0 +1,49 @@ +// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +// or more contributor license agreements. Licensed under the Elastic License; +// you may not use this file except in compliance with the Elastic License. + +//go:build kubernetes_inner + +package kubernetes_inside + +import ( + "fmt" + "io/fs" + "os" + "path/filepath" + "syscall" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestAgentPathsPermissions(t *testing.T) { + + uid := os.Getuid() + gid := os.Getgid() + + err := filepath.WalkDir("/usr/share/elastic-agent", func(walkPath string, d fs.DirEntry, err error) error { + if err != nil { + return fmt.Errorf("failed to walk path %s: %w", walkPath, err) + } + + info, err := d.Info() + if err != nil { + return fmt.Errorf("failed to get info of path %s: %w", walkPath, err) + } + + sysInfo, ok := info.Sys().(*syscall.Stat_t) + if !ok { + return nil + } + + if sysInfo.Gid != uint32(gid) && sysInfo.Uid != uint32(uid) { + // already owned + return fmt.Errorf("%s doesn't have correct permissions: has %d:%d (expected %d:%d)", walkPath, sysInfo.Uid, sysInfo.Gid, uid, gid) + } + + return nil + }) + + require.NoError(t, err) +}